airshipctl/docs/source/providers/cluster_api_openstack.md
Ratnopam Chakrabarti e122945ac7 Fix capo documentation
Replaced phase apply with phase run

Change-Id: I8d118c00f9439ce5f71a9a9f79bdd627972cc6ce
2020-10-12 15:24:02 +00:00

901 lines
41 KiB
Markdown
Executable File

# Airshipctl integration with Cluster API Openstack
## Overview
This document provides instructions on the usage of airshipctl, to perform the
following operations with openstack as infrastructure provider:
- Initialize the management cluster with cluster api, and cluster api openstack
provider components
- Create a target workload cluster with controlplane and worker machines on an openstack
cloud environment
## Workflow
A simple workflow that can be tested involves the following operations:
Initialize a management cluster with cluster api and openstack provider
components:
*`$ airshipctl phase run clusterctl-init-ephemeral`* or *`$ airshipctl phase run clusterctl-init-ephemeral --debug`*
Create a target workload cluster with control plane and worker nodes:
*`$ airshipctl phase run controlplane-target`*
*`$ airshipctl phase run workers-target`*
## Common Prerequisite
- Install [Docker](https://www.docker.com/)
- Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- Install [Kind](https://kind.sigs.k8s.io/)
- Install [Kustomize](https://kubernetes-sigs.github.io/kustomize/installation/binaries/)
- Install [Airshipctl](https://docs.airshipit.org/airshipctl/developers.html)
## Openstack Prerequisites
### Credentials
In order to comunicate with openstack cloud environment, following set of credentials are
needed to be generated.
The [env.rc](<https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/master/docs/env.rc>) script
sets the required environment variables related to credentials.
`source env.rc <path/to/clouds.yaml> <cloud>`
The following variables are set.
```bash
OPENSTACK_CLOUD: The cloud name which is used as second argument in the command above
OPENSTACK_CLOUD_YAML_B64: The secret used by capo to access OpenStack cloud
OPENSTACK_CLOUD_PROVIDER_CONF_B64: The content of cloud.conf used by OpenStack cloud
OPENSTACK_CLOUD_CACERT_B64: (Optional) The content of custom CA file which can be specified in the clouds.yaml
```
### SSH key pair
An ssh key-pair must be specified by setting the `OPENSTACK_SSH_KEY_NAME` environment variable.
A key-pair can be created by executing the following command
`openstack keypair create [--public-key <file> | --private-key <file>] <name>`
### Availability zone
The availability zone must be set as an environment variable `OPENSTACK_FAILURE_DOMAIN`.
### DNS server
The DNS servers must be set as an environment variable `OPENSTACK_DNS_NAMESERVERS`.
### External network
The openstack environment should have an external network already present.
The external network id can be specified by setting the `spec.externalNetworkId` of `OpenStackCluster` CRD of the cluster template.
The public network id can be obtained by using command
```bash
openstack network list --external
```
### Floating IP
A floating IP is automatically created and associated with the load balancer or controller node, however floating IP can also be
specified explicitly by setting the `spec.apiServerLoadBalancerFlotingIP` of `OpenStackCluster` CRD.
Floating ip can be created using `openstack floating ip create <public network>` command.
Note: Only user with admin role can create a floating IP with specific IP address.
### Operating system image
A cluster api compatible image is required for creating workload kubernetes clusters. The kubeadm bootstrap provider that capo uses
depends on some pre-installed software like a container runtime, kubelet, kubeadm and also on an up-to-date version of cloud-init.
The image can be referenced by setting an environment variable `OPENSTACK_IMAGE_NAME`.
#### Install Packer
$ mkdir packer
$ cd packer
$ wget <https://releases.hashicorp.com/packer/1.6.0/packer_1.6.0_linux_amd64.zip>
$ unzip packer_1.6.0_linux_amd64.zip
$ sudo mv packer /usr/local/bin/
#### Install Ansible
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt update
$ sudo apt install ansible
#### Build Cluster API Compliant VM Image
```bash
$ sudo -i
# apt install qemu-kvm libvirt-bin qemu-utils
$ sudo usermod -a -G kvm `<yourusername>`
$ sudo chown root:kvm /dev/kvm
```
Exit and log back in to make the change take place.
```bash
git clone <https://github.com/kubernetes-sigs/image-builder.git> image-builder
cd image-builder/images/capi/
vim packer/qemu/qemu-ubuntu-1804.json
```
Update the iso_url to `http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.5-server-amd64.iso`
Make sure to use the correct checksum value from
[ubuntu-releases](http://cdimage.ubuntu.com/releases/18.04.5/release/SHA256SUMS)
$ make build-qemu-ubuntu-1804
#### Upload Images to Openstack
$ openstack image create --container-format bare --disk-format qcow2 --file ubuntu-1804-kube-v1.16.14 ubuntu-1804-kube-v1.16.4
``` bash
$ openstack image list
+--------------------------------------+--------------------------+--------+
| ID | Name | Status |
+--------------------------------------+--------------------------+--------+
| 10e31af1-5414-4bae-9500-922db677e695 | amphora-x64-haproxy | active |
| 61bf8071-5e00-4806-83e0-612f8da03bf8 | cirros-0.5.1-x86_64-disk | active |
| 4fd894c7-9964-461b-bc9f-2e90fdade505 | ubuntu-1804-kube-v1.16.4 | active |
+--------------------------------------+--------------------------+--------+
```
## Getting Started
Kind is used to setup a kubernetes cluster, that will later be transformed
into a management cluster using airshipctl. The kind kubernetes cluster will be
initialized with cluster API and Cluster API openstack(CAPO) provider components.
$ export KIND_EXPERIMENTAL_DOCKER_NETWORK=bridge
$ kind create cluster --name capi-openstack --config ~/kind-cluster-config.yaml
```bash
Creating cluster "capi-openstack" ...
WARNING: Overriding docker network due to KIND_EXPERIMENTAL_DOCKER_NETWORK
WARNING: Here be dragons! This is not supported currently.
✓ Ensuring node image (kindest/node:v1.18.2) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-capi-openstack"
You can now use your cluster with:
kubectl cluster-info --context kind-capi-openstack
```
Check if all the pods are up.
$ kubectl get pods -A
```bash
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66bff467f8-2thc2 1/1 Running 0 2m43s
kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 2m43s
kube-system etcd-capi-openstack-control-plane 1/1 Running 0 2m58s
kube-system kindnet-xwp2x 1/1 Running 0 2m43s
kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 2m58s
kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 2m58s
kube-system kube-proxy-khhvd 1/1 Running 0 2m43s
kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 2m58s
local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 2m43s
```
## Create airshipctl configuration
$ mkdir ~/.airship
$ airshipctl config init
Run the below command to configure openstack manifest, and add it to airship config
$ airshipctl config set-manifest openstack_manifest --repo primary --url \
<https://opendev.org/airship/airshipctl> --branch master --primary \
--sub-path manifests/site/openstack-test-site --target-path /tmp/airship/
$ airshipctl config set-context kind-capi-openstack --manifest openstack_manifest
```bash
Context "kind-capi-openstack" created.
```
$ cp ~/.kube/config ~/.airship/kubeconfig
$ airshipctl config get-context
```bash
Context: kind-capi-openstack
contextKubeconf: kind-capi-openstack_target
manifest: openstack_manifest
LocationOfOrigin: /home/stack/.airship/kubeconfig
cluster: kind-capi-openstack_target
user: kind-capi-openstack
```
$ airshipctl config use-context kind-capi-openstack
$ airshipctl document pull --debug
```bash
[airshipctl] 2020/09/10 23:19:32 Reading current context manifest information from /home/stack/.airship/config
[airshipctl] 2020/09/10 23:19:32 Downloading primary repository airshipctl from https://opendev.org/airship/airshipctl into /tmp/airship/
[airshipctl] 2020/09/10 23:19:32 Attempting to download the repository airshipctl
[airshipctl] 2020/09/10 23:19:32 Attempting to clone the repository airshipctl from https://opendev.org/airship/airshipctl
[airshipctl] 2020/09/10 23:19:32 Attempting to open repository airshipctl
[airshipctl] 2020/09/10 23:19:32 Attempting to checkout the repository airshipctl from branch refs/heads/master
```
$ airshipctl config set-manifest openstack_manifest --target-path /tmp/airship/airshipctl
## Initialize Management cluster
Execute the following command to initialize the Management cluster with CAPI and CAPO components.
$ airshipctl phase run clusterctl-init-ephemeral --debug
```bash
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPD_AUTH_PROXY is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPM3_MANAGER is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CABPK_AUTH_PROXY is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CABPK_MANAGER is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CACPK_AUTH_PROXY is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPI_MANAGER is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPM3_AUTH_PROXY is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CACPK_MANAGER is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPD_MANAGER is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/implementations/reader.go:104: Verifying that variable CONTAINER_CAPI_AUTH_PROXY is allowed to be appended
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/events/processor.go:61: Received event: {4 {InitType {[]} {<nil>} {ApplyEventResourceUpdate ServersideApplied <nil>} {ResourceUpdateEvent <nil> <nil>} {PruneEventResourceUpdate Pruned <nil>} {DeleteEventResourceUpdate Deleted <nil>}} {<nil>} {ResourceUpdateEvent <nil> <nil>} {0 starting clusterctl init executor} {0 }}
[airshipctl] 2020/10/11 06:03:40 opendev.org/airship/airshipctl@/pkg/clusterctl/client/client.go:67: Starting cluster-api initiation
Installing the clusterctl inventory CRD
...
```
Wait for all the pods to be up.
$ kubectl get pods -A
```bash
NAMESPACE NAME READY STATUS RESTARTS AGE
capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-dfdf9877b-g44hd 2/2 Running 0 59s
capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-76c847457b-z2jtr 2/2 Running 0 58s
capi-system capi-controller-manager-7c7978f565-rk7qk 2/2 Running 0 59s
capi-webhook-system capi-controller-manager-748c57d64d-wjbnj 2/2 Running 0 60s
capi-webhook-system capi-kubeadm-bootstrap-controller-manager-65f979767f-bv6dr 2/2 Running 0 59s
capi-webhook-system capi-kubeadm-control-plane-controller-manager-7f5d88dcf9-k6kpf 2/2 Running 1 58s
capi-webhook-system capo-controller-manager-7d76dc9ddc-b9xhw 2/2 Running 0 57s
capo-system capo-controller-manager-79445d5984-k9fmc 2/2 Running 0 57s
cert-manager cert-manager-77d8f4d85f-nkg58 1/1 Running 0 71s
cert-manager cert-manager-cainjector-75f88c9f56-fcrc6 1/1 Running 0 72s
cert-manager cert-manager-webhook-56669d7fcb-cbzfn 1/1 Running 1 71s
kube-system coredns-66bff467f8-2thc2 1/1 Running 0 29m
kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 29m
kube-system etcd-capi-openstack-control-plane 1/1 Running 0 29m
kube-system kindnet-xwp2x 1/1 Running 0 29m
kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 29m
kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 29m
kube-system kube-proxy-khhvd 1/1 Running 0 29m
kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 29m
local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 29m
```
At this point, the management cluster is initialized with cluster api and cluster api openstack provider components.
## Create control plane and worker nodes
$ airshipctl phase run controlplane-target --debug
```bash
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:126: Getting kubeconfig file information from kubeconfig provider
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:131: Filtering out documents that shouldnt be applied to kubernetes from document bundle
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:115: WaitTimeout: 33m20s
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:77: Getting infos for bundle, inventory id is controlplane-target
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:107: Inventory Object config Map not found, auto generating Inventory object
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:114: Injecting Inventory Object: {"apiVersion":"v1","kind":"ConfigMap","metadata":{"creationTimestamp":null,"labels":{"cli-utils.sigs.k8s.io/inventory-id":"controlplane-target"},"name":"airshipit-controlplane-target","namespace":"airshipit"}}{nsfx:false,beh:unspecified} into bundle
[airshipctl] 2020/10/11 06:05:31 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:120: Making sure that inventory object namespace airshipit exists
secret/ostgt-cloud-config created
cluster.cluster.x-k8s.io/ostgt created
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane created
openstackcluster.infrastructure.cluster.x-k8s.io/ostgt created
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane created
5 resource(s) applied. 5 created, 0 unchanged, 0 configured
cluster.cluster.x-k8s.io/ostgt is NotFound: Resource not found
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is NotFound: Resource not found
openstackcluster.infrastructure.cluster.x-k8s.io/ostgt is NotFound: Resource not found
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane is NotFound: Resource not found
secret/ostgt-cloud-config is NotFound: Resource not found
secret/ostgt-cloud-config is Current: Resource is always ready
cluster.cluster.x-k8s.io/ostgt is InProgress:
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is Current: Resource is current
openstackcluster.infrastructure.cluster.x-k8s.io/ostgt is Current: Resource is current
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane is Current: Resource is current
cluster.cluster.x-k8s.io/ostgt is InProgress:
openstackcluster.infrastructure.cluster.x-k8s.io/ostgt is Current: Resource is current
cluster.cluster.x-k8s.io/ostgt is InProgress: Scaling up to 1 replicas (actual 0)
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is InProgress: Scaling up to 1 replicas (actual 0)
cluster.cluster.x-k8s.io/ostgt is InProgress:
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is InProgress:
cluster.cluster.x-k8s.io/ostgt is Current: Resource is Ready
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is Current: Resource is Ready
all resources has reached the Current status
```
$ airshipctl phase run workers-target --debug
```bash
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:126: Getting kubeconfig file information from kubeconfig provider
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:131: Filtering out documents that shouldnt be applied to kubernetes from document bundle
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/executor.go:115: WaitTimeout: 33m20s
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:77: Getting infos for bundle, inventory id is workers-target
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:107: Inventory Object config Map not found, auto generating Inventory object
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:114: Injecting Inventory Object: {"apiVersion":"v1","kind":"ConfigMap","metadata":{"creationTimestamp":null,"labels":{"cli-utils.sigs.k8s.io/inventory-id":"workers-target"},"name":"airshipit-workers-target","namespace":"airshipit"}}{nsfx:false,beh:unspecified} into bundle
[airshipctl] 2020/10/11 06:05:48 opendev.org/airship/airshipctl@/pkg/k8s/applier/applier.go:120: Making sure that inventory object namespace airshipit exists
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 created
machinedeployment.cluster.x-k8s.io/ostgt-md-0 created
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 created
3 resource(s) applied. 3 created, 0 unchanged, 0 configured
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found
machinedeployment.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current
machinedeployment.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current
all resources has reached the Current status
```
$ kubectl get po -A
```bash
NAMESPACE NAME READY STATUS RESTARTS AGE
capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-dfdf9877b-g44hd 2/2 Running 0 36m
capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-76c847457b-z2jtr 2/2 Running 0 36m
capi-system capi-controller-manager-7c7978f565-rk7qk 2/2 Running 0 36m
capi-webhook-system capi-controller-manager-748c57d64d-wjbnj 2/2 Running 0 36m
capi-webhook-system capi-kubeadm-bootstrap-controller-manager-65f979767f-bv6dr 2/2 Running 0 36m
capi-webhook-system capi-kubeadm-control-plane-controller-manager-7f5d88dcf9-k6kpf 2/2 Running 1 36m
capi-webhook-system capo-controller-manager-7d76dc9ddc-b9xhw 2/2 Running 0 36m
capo-system capo-controller-manager-79445d5984-k9fmc 2/2 Running 0 36m
cert-manager cert-manager-77d8f4d85f-nkg58 1/1 Running 0 36m
cert-manager cert-manager-cainjector-75f88c9f56-fcrc6 1/1 Running 0 36m
cert-manager cert-manager-webhook-56669d7fcb-cbzfn 1/1 Running 1 36m
kube-system coredns-66bff467f8-2thc2 1/1 Running 0 64m
kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 64m
kube-system etcd-capi-openstack-control-plane 1/1 Running 0 64m
kube-system kindnet-xwp2x 1/1 Running 0 64m
kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 64m
kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 64m
kube-system kube-proxy-khhvd 1/1 Running 0 64m
kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 64m
local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 64m
```
To check logs run the below command
$ kubectl logs capo-controller-manager-79445d5984-k9fmc -n capo-system --all-containers=true -f
```bash
I0910 23:36:54.768316 1 listener.go:44] controller-runtime/metrics "msg"="metrics server is starting to listen" "addr"="127.0.0.1:8080"
I0910 23:36:54.768890 1 main.go:235] setup "msg"="starting manager"
I0910 23:36:54.769149 1 leaderelection.go:242] attempting to acquire leader lease capo-system/controller-leader-election-capo...
I0910 23:36:54.769199 1 internal.go:356] controller-runtime/manager "msg"="starting metrics server" "path"="/metrics"
I0910 23:36:54.853723 1 leaderelection.go:252] successfully acquired lease capo-system/controller-leader-election-capo
I0910 23:36:54.854706 1 controller.go:164] controller-runtime/controller "msg"="Starting EventSource" "controller"="openstackcluster" "source"={" Type":{"metadata":{"creationTimestamp":null},"spec":{"cloudsSecret":null,"cloudName":"","network":{},"subnet":{},"managedAPIServerLoadBalancer":false,"m anagedSecurityGroups":false,"caKeyPair":{},"etcdCAKeyPair":{},"frontProxyCAKeyPair":{},"saKeyPair":{},"controlPlaneEndpoint":{"host":"","port":0}},"stat us":{"ready":false}}}
I0910 23:36:54.854962 1 controller.go:164] controller-runtime/controller "msg"="Starting EventSource" "controller"="openstackmachine" "source"={" Type":{"metadata":{"creationTimestamp":null},"spec":{"cloudsSecret":null,"cloudName":"","flavor":"","image":""},"status":{"ready":false}}}
```
$ kubectl get machines
```bash
NAME PROVIDERID PHASE
ostgt-control-plane-cggt7 openstack://a6da4363-9419-4e14-b67a-3ce86da198c4 Running
ostgt-md-0-6b564d74b8-8h8d8 openstack://23fd5b75-e3f4-4e89-b900-7a6873a146c2 Running
ostgt-md-0-6b564d74b8-pj4lm openstack://9b8323a2-757f-4905-8006-4514862fde75 Running
ostgt-md-0-6b564d74b8-wnw8l openstack://1a8f10da-5d12-4c50-a60d-f2e24a387611 Running
```
$ kubectl get secrets
```bash
NAME TYPE DATA AGE
default-token-vfcm7 kubernetes.io/service-account-token 3 114m
ostgt-ca Opaque 2 47m
ostgt-cloud-config Opaque 2 51m
ostgt-control-plane-gd2gq cluster.x-k8s.io/secret 1 47m
ostgt-etcd Opaque 2 47m
ostgt-kubeconfig Opaque 1 47m
ostgt-md-0-j76jg cluster.x-k8s.io/secret 1 44m
ostgt-md-0-kdjsv cluster.x-k8s.io/secret 1 44m
ostgt-md-0-q4vmn cluster.x-k8s.io/secret 1 44m
ostgt-proxy Opaque 2 47m
ostgt-sa Opaque 2 47m
```
$ kubectl --namespace=default get secret/ostgt-kubeconfig -o jsonpath={.data.value} | base64 --decode > ./ostgt.kubeconfig
$ kubectl get pods -A --kubeconfig ~/ostgt.kubeconfig
```bash
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-7865ff46b6-8pbnq 1/1 Running 0 47m
kube-system calico-node-7kpjb 1/1 Running 0 44m
kube-system calico-node-d8dcc 1/1 Running 0 45m
kube-system calico-node-mdwnt 1/1 Running 0 47m
kube-system calico-node-n2qr8 1/1 Running 0 45m
kube-system coredns-6955765f44-dkvwq 1/1 Running 0 47m
kube-system coredns-6955765f44-p4mbh 1/1 Running 0 47m
kube-system etcd-ostgt-control-plane-vpmqg 1/1 Running 0 47m
kube-system kube-apiserver-ostgt-control-plane-vpmqg 1/1 Running 0 47m
kube-system kube-controller-manager-ostgt-control-plane-vpmqg 1/1 Running 0 47m
kube-system kube-proxy-j6msn 1/1 Running 0 44m
kube-system kube-proxy-kgxvq 1/1 Running 0 45m
kube-system kube-proxy-lfmlf 1/1 Running 0 45m
kube-system kube-proxy-zq26j 1/1 Running 0 47m
kube-system kube-scheduler-ostgt-control-plane-vpmqg 1/1 Running 0 47m
```
$ kubectl get nodes --kubeconfig ~/ostgt.kubeconfig
```bash
NAME STATUS ROLES AGE VERSION
ostgt-control-plane-vpmqg Ready master 49m v1.17.3
ostgt-md-0-6p2f9 Ready <none> 46m v1.17.3
ostgt-md-0-h8hn9 Ready <none> 47m v1.17.3
ostgt-md-0-k9k66 Ready <none> 46m v1.17.3
```
$ kubectl get cs --kubeconfig ~/ostgt.kubeconfig
```bash
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
```
Now, the control plane and worker node are created on openstack.
![Machines](../img/openstack-machines.png)
## Tear Down Clusters
In order to delete the cluster run the below command. This will delete
the control plane, workers and all other resources
associated with the cluster on openstack.
```bash
$ kubectl delete cluster ostgt
cluster.cluster.x-k8s.io "ostgt" deleted
```
$ kind delete cluster --name capi-openstack
## Reference
### Installation Using Devstack
- Install [Devstack](https://docs.openstack.org/devstack/latest/guides/devstack-with-lbaas-v2.html)
- Create `ubuntu-1910-kube-v1.17.3.qcow2` image in the devstack.
Download a capi compatible image for ubuntu OS.
```bash
wget https://github.com/sbueringer/image-builder/releases/download/v1.17.3-04/ubuntu-1910-kube-v1.17.3.qcow2
openstack image create --container-format bare --disk-format qcow2 --file ubuntu-1910-kube-v1.17.3.qcow2 ubuntu-1910-kube-v1.17.3
```
Check if the image status is `active`
```bash
stack@stackdev-ev:/opt/stack/devstack$ openstack image list
+--------------------------------------+--------------------------+--------+
| ID | Name | Status |
+--------------------------------------+--------------------------+--------+
| 83002c1d-436d-4007-bea1-3ffc94fa193b | amphora-x64-haproxy | active |
| a801c914-a0b9-485a-ba5f-246e912cb656 | cirros-0.5.1-x86_64-disk | active |
| 8e8fc7a8-cfe0-4251-bdde-8600838f2ed8 | ubuntu-1910-kube-v1.17.3 | active |
```
- Generate credentials
In devstack environment, normally the `clouds.yaml` file is found at `etc/openstack/` location.
Execute the following command to generate the cloud credentials for devstack
```bash
wget https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-openstack/master/templates/env.rc -O /tmp/env.rc
source /tmp/env.rc /etc/openstack/clouds.yaml devstack
```
A snippet of sample clouds.yaml file can be seen below for cloud `devstack`.
```bash
clouds:
devstack:
auth:
auth_url: http://10.0.4.4/identity
project_id: f3deb6e94bee4addaed3ba42d6ffaeba
user_domain_name: Default
username: demo
password: pass
region_name: RegionOne
```
The list of project_id-s can be retrieved by `openstack project list` in the devstack environment.
- Ensure that `demo` user has `admin` rights so that floating ip-s can be created at the time of
workload cluster deployment.
```bash
cd /opt/stack/devstack
export OS_USERNAME=admin
$ . ./openrc
$ openstack role add --project demo --user demo admin
```
- Create Floating IP
To create floating ip, following command can be used
`openstack floating ip create public --floating-ip-address $FLOATING_IP_ADDRESS`
where `FLOATING_IP_ADDRESS` is the specified ip address and `public` is the name of
the external network in devstack.
`openstack floating ip list` command shows the list of all floating ip-s.
- Allow ssh access to controlplane and worker nodes
Cluster api creates following security groups if `spec.managedSecurityGroups` of
`OpenStackCluster` CRD is set to true.
- k8s-cluster-default-`<CLUSTER-NAME>`-secgroup-controlplane (for control plane)
- k8s-cluster-default-`<CLUSTER-NAME>`-secgroup-worker (for worker nodes)
These security group rules include the kubeadm's
[Check required ports](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#check-required-ports)
so that each node can not be logged in through ssh by default.
If ssh access to the nodes is required then follow the below steps -
Create a security group allowing ssh access
```bash
openstack security group create --project demo --project-domain Default allow-ssh
openstack security group rule create allow-ssh --protocol tcp --dst-port 22:22 --remote-ip 0.0.0.0/0
```
Add the security group to `OpenStackMachineTemplate` CRD as below
```bash
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: OpenStackMachineTemplate
metadata:
name: ${CLUSTER_NAME}-control-plane
spec:
template:
spec:
securityGroups:
- name: allow-ssh
```
### Provider Manifests
Provider Configuration for Capo is referenced from
[Config](https://github.com/kubernetes-sigs/cluster-api-provider-openstack/tree/master/config)
$ tree airshipctl/manifests/function/capo
```bash
└── v0.3.1
├── certmanager
│ ├── certificate.yaml
│ ├── kustomization.yaml
│ └── kustomizeconfig.yaml
├── crd
│ ├── bases
│ │ ├── infrastructure.cluster.x-k8s.io_openstackclusters.yaml
│ │ ├── infrastructure.cluster.x-k8s.io_openstackmachines.yaml
│ │ └── infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml
│ ├── kustomization.yaml
│ ├── kustomizeconfig.yaml
│ └── patches
│ ├── cainjection_in_openstackclusters.yaml
│ ├── cainjection_in_openstackmachines.yaml
│ ├── cainjection_in_openstackmachinetemplates.yaml
│ ├── webhook_in_openstackclusters.yaml
│ ├── webhook_in_openstackmachines.yaml
│ └── webhook_in_openstackmachinetemplates.yaml
├── default
│ ├── kustomization.yaml
│ ├── manager_role_aggregation_patch.yaml
│ └── namespace.yaml
├── kustomization.yaml
├── manager
│ ├── kustomization.yaml
│ ├── manager.yaml
│ ├── manager_auth_proxy_patch.yaml
│ ├── manager_image_patch.yaml
│ └── manager_pull_policy.yaml
├── patch_crd_webhook_namespace.yaml
├── rbac
│ ├── auth_proxy_role.yaml
│ ├── auth_proxy_role_binding.yaml
│ ├── auth_proxy_service.yaml
│ ├── kustomization.yaml
│ ├── leader_election_role.yaml
│ ├── leader_election_role_binding.yaml
│ ├── role.yaml
│ └── role_binding.yaml
└── webhook
├── kustomization.yaml
├── kustomizeconfig.yaml
├── manager_webhook_patch.yaml
├── manifests.yaml
├── service.yaml
└── webhookcainjection_patch.yaml
```
### Kind Configuration
```bash
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "127.0.0.1"
apiServerPort: 37533
nodes:
- role: control-plane
extraMounts:
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
- hostPath: /tmp/airship/airshipctl/tools/deployment/certificates
containerPath: /etc/kubernetes/pki
kubeadmConfigPatches:
- |
kind: ClusterConfiguration
certificatesDir: /etc/kubernetes/pki
```
### Capo Phases
```bash
/airshipctl/manifests/capo-phases$ tree
.
├── cluster-map.yaml
├── executors.yaml
├── kubeconfig.yaml
├── kustomization.yaml
├── phases.yaml
└── plan.yaml
```
$ cat phases.yaml
```bash
---
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: clusterctl-init-ephemeral
clusterName: kind-capi-openstack
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: Clusterctl
name: clusterctl_init
---
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: controlplane-target
clusterName: kind-capi-openstack
config:
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: KubernetesApply
name: kubernetes-apply
documentEntryPoint: manifests/site/openstack-test-site/target/controlplane
---
apiVersion: airshipit.org/v1alpha1
kind: Phase
metadata:
name: workers-target
clusterName: kind-capi-openstack
config:
cluster: kind-capi-openstack
executorRef:
apiVersion: airshipit.org/v1alpha1
kind: KubernetesApply
name: kubernetes-apply
documentEntryPoint: manifests/site/openstack-test-site/target/workers
```
### Cluster Templates
airshipctl/manifests/function/k8scontrol-capo contains cluster.yaml, controlplane.yaml templates.
```bash
cluster.yaml: Contains CRDs Cluster, OpenstackCluster, Secret
controlplane.yaml: Contains CRDs KubeadmControlPlane, OpenstackMachineTemplate
```
$ tree airshipctl/manifests/function/k8scontrol-capo
```bash
airshipctl/manifests/function/k8scontrol-capo
├── cluster.yaml
├── controlplane.yaml
└── kustomization.yaml
```
airshipctl/manifests/function/workers-capo contains workers.yaml
```bash
workers.yaml: Contains CRDs Cluster, OpenstackCluster, Secret
```
$ tree airshipctl/manifests/function/workers-capo
```bash
airshipctl/manifests/function/workers-capo
.
├── kustomization.yaml
└── workers.yaml
```
### Test Site Manifests
#### openstack-test-site/target
Following phase entrypoints reside in the openstack-test-site.
```bash
controlplane - Patches templates in manifests/function/k8scontrol-capo
workers - Patches template in manifests/function/workers-capo
```
Note: `airshipctl phase run clusterctl-init-ephemeral` initializes all the provider components including the openstack infrastructure provider component.
#### Patch Merge Strategy
Json and strategic merge patches are applied on templates in `manifests/function/k8scontrol-capo`
from `airshipctl/manifests/site/openstack-test-site/target/controlplane` when
`airshipctl phase run controlplane-target` command is executed
Json and strategic merge patches are applied on templates in `manifests/function/workers-capo`
from `airshipctl/manifests/site/openstack-test-site/target/workers` when
`airshipctl phase run workers-target` command is executed
```bash
controlplane/control_plane_ip.json: patches control plane ip in template function/k8scontrol-capo/cluster.yaml
controlplane/dns_servers.json: patches dns servers in template function/k8scontrol-capo/cluster.yaml
controlplane/external_network_id.json: patches external network id in template function/k8scontrol-capo/cluster.yaml
cluster_clouds_yaml_patch.yaml: patches clouds.yaml configuration in template function/k8scontrol-capo/cluster.yaml
controlplane/control_plane_ip_patch.yaml: patches controlplane ip in template function/k8scontrol-capo/controlplane.yaml
controlplane/control_plane_config_patch.yaml: patches cloud configuration in template function/k8scontrol-capo/controlplane.yaml
controlplane/ssh_key_patch.yaml: patches ssh key in template function/k8scontrol-capo/controlplane.yaml
controlplane/control_plane_machine_count_patch.yaml: patches controlplane replica count in template function/k8scontrol-capo/controlplane.yaml
controlplane/control_plane_machine_flavor_patch.yaml: patches controlplane machine flavor in template function/k8scontrol-capo/controlplane.yaml
workers/workers_cloud_conf_patch.yaml: patches cloud configuration in template function/workers-capo/workers.yaml
workers/workers_machine_count_patch.yaml: patches worker replica count in template function/workers-capo/workers.yaml
workers/workers_machine_flavor_patch.yaml: patches worker machine flavor in template function/workers-capo/workers.yaml
workers/workers_ssh_key_patch.yaml: patches ssh key in template function/workers-capo/workers.yaml
```
## Software Version Information
All the instructions provided in the document have been tested using the software and
version, provided in this section.
### Docker
```bash
$ docker version
Client: Docker Engine - Community
Version: 19.03.12
API version: 1.40
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:45:36 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.12
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 48a66213fe
Built: Mon Jun 22 15:44:07 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
```
### Kind
```bash
$ kind version
kind v0.8.1 go1.14.2 linux/amd64
```
### Kubectl
```bash
$ kubectl version --short
Client Version: v1.17.4
Server Version: v1.18.2
```
### Go
```bash
$ go version
go version go1.10.4 linux/amd64
```
### Kustomize
```bash
$ kustomize version
{Version:kustomize/v3.8.0 GitCommit:6a50372dd5686df22750b0c729adaf369fbf193c BuildDate:2020-07-05T14:08:42Z GoOs:linux GoArch:amd64}
```
### OS
```bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```
## Virtual Machine Specification
All the instructions in the document were perfomed on VM(with nested virtualization enabled)
with 16 vCPUs, 64 GB RAM.