Sunday, November 17, 2019

Deploying OpenShift IPI Baremetal Disconnected


The following blog is a write up of the steps I used to generate a OpenShift IPI disconnected baremetal install. In this configuration we first mirror down the images to a local repository. Then deploy the Openshift cluster onto virtual machines that are mimicking a baremetal environment with vBMC being used as the IPMI interface into the virtual machines.  Please note that while this was demonstrated in a virtual setting these steps should also work with physical hardware.

Lab Setup:

Physical node specification:

Processors: i7 - 8 vcpus
Memory: 32gb
Disk: 512gb M2 SSD
Single NIC with 2 vlans (external and provisioning) tagged in
Nested virtualization should be enabled

Virtual machine Node specification:

Processor: Passthrough from physical node - 4 vcpus
Memory: 16gb
Disk: 60gb raw image
Two NICs ens3 (provisioning) ens4 (external) - no tags - dhcp interfaces
IPMI: Provided via centralized Virtual BMC controller

Lab Diagram:


Predefined DNS records:

*.apps.kni5  IN A 192.168.0.197
ns1.kni5  IN A 192.168.0.198
api.kni5  IN A 192.168.0.199
master-0.kni5         IN A 192.168.0.200
master-1.kni5         IN A 192.168.0.201
master-2.kni5         IN A 192.168.0.202

Cluster and user definitions:

Cluster Name: kni5
Domain Name: schmaustech.com
Username for installation: bschmaus

Preparing Provisioning Node:

The first step in preparing the provisioning node is to install, kickstart or image the provisioning node with RHEL8 and register the host.  I leverage an ISO image local on NUC-1 with an embedded kickstart file that way I can rebuild my provisioning node on the fly and start off with a fresh install.

Once the provisioning node is installed make sure the following packages are installed:

kexec-tools
@development (package group)
git
usbredir
golang
libXv
virt-install
libvirt
libvirt-devel
libselinux-utils
qemu-kvm
mkisofs

Next lets make sure the username used for installation has passwordless sudo access.  This is more about convenience give a lot of the commands require root and or sudo access:

# cat << EOF > /etc/sudoers.d/openshift
Defaults:bschmaus !requiretty
bschmaus ALL = (root) NOPASSWD:ALL
EOF
# chmod 600 /etc/sudoers.d/openshift

Unfortunately at this time selinux does need to be set to permissive so we will do that now:

# sudo setenforce permissive
# sudo sed -i "s/=enforcing/=permissive/g" /etc/selinux/config

For the bootstrap node to boot on this virtual machine we need to ensure a default storage pool exists.  On a RHEL8 installation this pool does not seem to exist out of the box so lets create it:

# sudo virsh pool-define-as --name default --type dir --target /var/lib/libvirt/images
# sudo virsh pool-start default
# sudo virsh pool-autostart default
# sudo usermod --append --groups libvirt bschmaus

The Openshift installer expects there to be a baremetal and provisioning interface on the provisioning node so lets configure them with the following:

# export PROV_CONN=ens3
# export MAIN_CONN=ens4
# sudo nmcli connection add ifname provisioning type bridge con-name provisioning
# sudo nmcli con add type bridge-slave ifname "$PROV_CONN" master provisioning
# sudo nmcli connection add ifname baremetal type bridge con-name baremetal
# sudo nmcli con add type bridge-slave ifname "$MAIN_CONN" master baremetal
# sudo nmcli con down "System $MAIN_CONN"; sudo pkill dhclient; sudo dhclient baremetal
# sudo nmcli connection modify provisioning ipv4.addresses 172.22.0.1/24 ipv4.method manual
# sudo nmcli con down provisioning
# sudo nmcli con up provisioning
# sudo ip a show $PROV_CONN;ip a show $MAIN_CONN; ip a show provisioning; ip a show baremetal
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master provisioning state UP group default qlen 1000
    link/ether 52:54:00:9e:01:ec brd ff:ff:ff:ff:ff:ff
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master baremetal state UP group default qlen 1000
    link/ether 52:54:00:07:98:b1 brd ff:ff:ff:ff:ff:ff
8: provisioning: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:9e:01:ec brd ff:ff:ff:ff:ff:ff
    inet 172.22.0.1/24 brd 172.22.0.255 scope global noprefixroute provisioning
       valid_lft forever preferred_lft forever
    inet6 fe80::b189:6c77:d795:57dc/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
7: baremetal: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:07:98:b1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.246/24 brd 192.168.0.255 scope global dynamic noprefixroute baremetal
       valid_lft 366sec preferred_lft 366sec
    inet6 fe80::495e:1100:2ad3:851e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

At this time we should also pull the latest oc binary and openshift-baremetal-install binary.  The oc command will be used to mirror the repository and also validate the cluster is up once installation is complete:

# export VERSION=$(curl -s https://mirror.openshift.com/pub/openshift-v4/clients/ocp-dev-preview/latest/release.txt | grep 'Name:' | awk -F: '{print $2}' | xargs)
# export RELEASE_IMAGE=$(curl -s https://mirror.openshift.com/pub/openshift-v4/clients/ocp-dev-preview/latest/release.txt | grep 'Pull From: quay.io' | awk -F ' ' '{print $3}' | xargs)
# export pullsecret_file=/home/bschmaus/pull-secret.json
# export cmd=openshift-baremetal-install
# export extract_dir=$(pwd)
# curl -s https://mirror.openshift.com/pub/openshift-v4/clients/ocp-dev-preview/latest/openshift-client-linux-$VERSION.tar.gz | tar zxvf - oc
# sudo cp /home/bschmaus/oc /usr/local/bin/oc
# /usr/local/bin/oc adm release extract --registry-config "${pullsecret_file}" --command=$cmd --to "${extract_dir}" ${RELEASE_IMAGE}
# sudo cp /home/bschmaus/openshift-baremetal-install /usr/local/bin/openshift-baremetal-install 

Create Initial Install-Config.yaml and Local Image Repository:

Now that we have prepared the provisioning host, we need to first create our initial install-config.yaml file.   The file should look similar to the sample below but adjusted for your environment (Note: RELEASEVERSION should be typed as in example as we will change that in later step):

apiVersion: v1
baseDomain: schmaustech.com
metadata:
  name: kni5
networking:
  machineCIDR: 192.168.0.0/24
compute:
- name: worker
  replicas: 0
controlPlane:
  name: master
  replicas: 3
  platform:
    baremetal: {}
platform:
  baremetal:
    apiVIP: 192.168.0.199
    ingressVIP: 192.168.0.197
    dnsVIP: 192.168.0.198
    hosts:
      - name: master-0
        role: master
        bmc:
          address: ipmi://192.168.0.11:6241
          username: admin
          password: password
        bootMACAddress: 52:54:00:3d:04:ae
        hardwareProfile: default
      - name: master-1
        role: master
        bmc:
          address: ipmi://192.168.0.11:6242
          username: admin
          password: password
        bootMACAddress: 52:54:00:0f:91:f3
        hardwareProfile: default
      - name: master-2
        role: master
        bmc:
          address: ipmi://192.168.0.11:6243
          username: admin
          password: password
        bootMACAddress: 52:54:00:ee:d2:f2
        hardwareProfile: default
sshKey: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDP+5QkRCiuhsYItXj7DzLcOIs2RbCgpMzDtPlt/hfLnDkLGozYIFapMp+o4l+6ornbZ3L+hYE0T8SyvyYVWfm1XpPcVgUIW6qp7yfEyTSRhpGnoY74PD33FIf6BtU2HoFLWjQcE6OrQOF0wijI3fgL0jSzvAxvYoXU/huMx/kI2jBcWEq5cADRfvpeYXhVEJLrIIOepoAZE1syaPT7jQEoLDfvxrDZPKObCOI2vzLiAQXI7gK1uc9YDb6IEA/4Ik4eV2R1+VCgKhgk5RUqn69+8a1o783g1tChKuLwA4K9lyEAbFBwlHMctfNOLeC1w+bYpDXH/3GydcYfq79/18dVd+xEUlzzC+2/qycWG36C1MxUZa2fXvSRWLnpkLcxtIes4MikFeIr3jkJlFUzITigzvFrKa2IKaJzQ53WsE++LVnKJfcFNLtWfdEOZMowG/KtgzSSac/iVEJRM2YTIJsQsqhhI4PTrqVlUy/NwcXOFfUF/NkF2deeUZ21Cdn+bKZDKtFu2x+ujyAWZKNq570YaFT3a4TrL6WmE9kdHnJOXYR61Tiq/1fU+y0fv1d0f1cYr4+mNRCGIZoQOgJraF7/YluLB23INkJgtbah/0t1xzSsQ59gzFhRlLkW9gQDekj2tOGJmZIuYCnTXGiqXHnri2yAPexgRiaFjoM3GCpsWw== bschmaus@lap1.schmaustech.com'
imageContentSources:
- mirrors:
  - rhel8-ocp-auto.schmaustech.com:5000/ocp4/openshift4
  source: registry.svc.ci.openshift.org/ocp/RELEASEVERSION
- mirrors:
  - rhel8-ocp-auto.schmaustech.com:5000/ocp4/openshift4
  source: registry.svc.ci.openshift.org/ocp/release
pullSecret: 'PULL SECRET HERE'

Lets also create a pull-secret.json file that has the OpenShift pull-secret credentials so we can access the Openshift repository (Note: PULL-SECRET-JSON needs to be the actual pull-secret one gets from OpenShift):

# echo 'PULL-SECRET-JSON' > /home/bschmaus/pull-secret-json

Now that we have the initial install-config.yaml that we will use to deploy the OpenShift cluster lets change gears and configure the local image repository on the provisioning node.   The steps below outline what is needed to configure the repository:

# sudo yum -y install podman httpd httpd-tools
# sudo mkdir -p /opt/registry/{auth,certs,data}
# sudo openssl req -newkey rsa:4096 -nodes -sha256 -keyout /opt/registry/certs/domain.key -x509 -days 365 -out /opt/registry/certs/domain.crt -subj "/C=US/ST=Minnesota/L=Brooklyn Park/O=Red Hat/OU=Engineering/CN=rhel8-ocp-auto.schmaustech.com"
# sudo cp /opt/registry/certs/domain.crt /etc/pki/ca-trust/source/anchors/
# sudo update-ca-trust extract
# sudo htpasswd -bBc /opt/registry/auth/htpasswd dummy dummy
# sudo firewall-cmd --add-port=5000/tcp --zone=libvirt  --permanent
# sudo firewall-cmd --add-port=5000/tcp --zone=public   --permanent
# sudo firewall-cmd --add-service=http  --permanent
# sudo firewall-cmd --reload
# sudo podman create --name poc-registry -p 5000:5000 -v /opt/registry/data:/var/lib/registry:z -v /opt/registry/auth:/auth:z -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry" -e "REGISTRY_HTTP_SECRET=ALongRandomSecretForRegistry" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -v /opt/registry/certs:/certs:z -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key docker.io/library/registry:2
# sudo podman start poc-registry

Test that the repository is working with the following test:

# curl -u dummy:dummy -k https://rhel8-ocp-auto.schmaustech.com:5000/v2/_catalog


Update Install-Config.yaml Pull Secret & Certificate:

Now we need to update the pull-secret in our install-config.yaml file to reference the local repository credentials we used above.  To do this we first need to capture the base64 output for the user/password we configured for the local mirror which was dummy and dummy:

# echo -n 'dummy:dummy' | base64 -w0
ZHVtbXk6ZHVtbXk=

With the output above place it into a string like the sample below making sure to update the repository hostname as well to match the environment.  Save the contents to a file called local_pull_secret:

# cat << 'EOF' > /home/bschmaus/local_pull_secret
pullSecret: '{ "auths": { "rhel8-ocp-auto.schmaustech.com:5000": {"auth": "ZHVtbXk6ZHVtbXk=","email": "bschmaus@redhat.com"} } }'
EOF

Now lets inject that local_pull_secret into our install-config.yaml file:

# sed  -i '/^pullSecret/d' /home/bschmaus/install-config.yaml
# cat /home/bschmaus/local_pull_secret >> /home/bschmaus/install-config.yaml

Since we also created a cert above and our install-config.yaml file will need to connect to the local repository lets go ahead and add that cert to the install-config.yaml:

# sudo cp /opt/registry/certs/domain.crt /home/bschmaus/domain.crt
# sed -i -e 's/^/  /' /home/bschmaus/domain.crt
# echo "additionalTrustBundle: |" >> /home/bschmaus/install-config.yaml
# cat /home/bschmaus/domain.crt >> /home/bschmaus/install-config.yaml

Once the install-config.yaml file is updated with both the local repository pull-secret and domain cert our install-config.yaml will look something like the following:

apiVersion: v1
baseDomain: schmaustech.com
metadata:
  name: kni5
networking:
  machineCIDR: 192.168.0.0/24
compute:
- name: worker
  replicas: 0
controlPlane:
  name: master
  replicas: 3
  platform:
    baremetal: {}
platform:
  baremetal:
    apiVIP: 192.168.0.199
    ingressVIP: 192.168.0.197
    dnsVIP: 192.168.0.198
    hosts:
      - name: master-0
        role: master
        bmc:
          address: ipmi://192.168.0.11:6241
          username: admin
          password: password
        bootMACAddress: 52:54:00:3d:04:ae
        hardwareProfile: default
      - name: master-1
        role: master
        bmc:
          address: ipmi://192.168.0.11:6242
          username: admin
          password: password
        bootMACAddress: 52:54:00:0f:91:f3
        hardwareProfile: default
      - name: master-2
        role: master
        bmc:
          address: ipmi://192.168.0.11:6243
          username: admin
          password: password
        bootMACAddress: 52:54:00:ee:d2:f2
        hardwareProfile: default
sshKey: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDP+5QkRCiuhsYItXj7DzLcOIs2RbCgpMzDtPlt/hfLnDkLGozYIFapMp+o4l+6ornbZ3L+hYE0T8SyvyYVWfm1XpPcVgUIW6qp7yfEyTSRhpGnoY74PD33FIf6BtU2HoFLWjQcE6OrQOF0wijI3fgL0jSzvAxvYoXU/huMx/kI2jBcWEq5cADRfvpeYXhVEJLrIIOepoAZE1syaPT7jQEoLDfvxrDZPKObCOI2vzLiAQXI7gK1uc9YDb6IEA/4Ik4eV2R1+VCgKhgk5RUqn69+8a1o783g1tChKuLwA4K9lyEAbFBwlHMctfNOLeC1w+bYpDXH/3GydcYfq79/18dVd+xEUlzzC+2/qycWG36C1MxUZa2fXvSRWLnpkLcxtIes4MikFeIr3jkJlFUzITigzvFrKa2IKaJzQ53WsE++LVnKJfcFNLtWfdEOZMowG/KtgzSSac/iVEJRM2YTIJsQsqhhI4PTrqVlUy/NwcXOFfUF/NkF2deeUZ21Cdn+bKZDKtFu2x+ujyAWZKNq570YaFT3a4TrL6WmE9kdHnJOXYR61Tiq/1fU+y0fv1d0f1cYr4+mNRCGIZoQOgJraF7/YluLB23INkJgtbah/0t1xzSsQ59gzFhRlLkW9gQDekj2tOGJmZIuYCnTXGiqXHnri2yAPexgRiaFjoM3GCpsWw== bschmaus@bschmaus.remote.csb'
imageContentSources:
- mirrors:
  - rhel8-ocp-auto.schmaustech.com:5000/ocp4/openshift4
  source: registry.svc.ci.openshift.org/ocp/RELEASEVERSION
- mirrors:
  - rhel8-ocp-auto.schmaustech.com:5000/ocp4/openshift4
  source: registry.svc.ci.openshift.org/ocp/release
pullSecret: '{ "auths": { "rhel8-ocp-auto.schmaustech.com:5000": {"auth": "ZHVtbXk6ZHVtbXk=","email": "bschmaus@redhat.com"} } }'
additionalTrustBundle: |
  -----BEGIN CERTIFICATE-----
  MIIF9zCCA9+gAwIBAgIUJhBYhR40iyQOEWifRhKAjwupm4gwDQYJKoZIhvcNAQEL
  BQAwgYoxCzAJBgNVBAYTAlVTMRIwEAYDVQQIDAlNaW5uZXNvdGExFjAUBgNVBAcM
  DUJyb29rbHluIFBhcmsxEDAOBgNVBAoMB1JlZCBIYXQxFDASBgNVBAsMC0VuZ2lu
  ZWVyaW5nMScwJQYDVQQDDB5yaGVsOC1vY3AtYXV0by5zY2htYXVzdGVjaC5jb20w
  HhcNMTkxMTE3MjEwNjEzWhcNMjAxMTE2MjEwNjEzWjCBijELMAkGA1UEBhMCVVMx
  EjAQBgNVBAgMCU1pbm5lc290YTEWMBQGA1UEBwwNQnJvb2tseW4gUGFyazEQMA4G
  A1UECgwHUmVkIEhhdDEUMBIGA1UECwwLRW5naW5lZXJpbmcxJzAlBgNVBAMMHnJo
  ZWw4LW9jcC1hdXRvLnNjaG1hdXN0ZWNoLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQAD
  ggIPADCCAgoCggIBAMiiLRYITGwaOXext9cTOpemfwBjfKx0eREEpqww9nz5qRPn
  a0NK9Q5zgpieQvGWAN8y9c6wK0aUS4SRcFSx8RVbjP2L4p3ii0UsH6xP6JqHtfIg
  ynbqco6CyfSq7k+GwmoMLFx0Tki3Ta6syVQ9pN/YctTPIeIBMOXkSeOxNkn8dtdG
  oiCXS2OB0cW+wf3INp48Cc2zbbc+QmMw/LQlJIZcrP/C/Luh+fGiOt5XbrFD2Ain
  FYkKHOEzGucuEHDC7f/wLqLkwUf6iN4aB0fVU7kdYn1C1aZJhmlY5tSzR3eRvNsL
  QgFPfkHI647OTbDA8R4VNRRgkza+dEgEvLUbAyeQ7JztcFfnncWlDuvZdj6MCstR
  MND4lw3Ig0AK9PYXb5ui5g57ms7tInmqVJKb/9Xp9DKSWEUEOe+TQBeZ6spWmQjg
  GcPwuX5g+9RHh4iYmClxclDrZ6k6o6NQY9ldXQeI6kNVHacvg2S7iaWXFrshDtk4
  ss5Lvlag4/+yLJUIiWeIyG8yBkDlH7d+OV8F9rhf86J7tgbcA+pxms0v11Ot0I4n
  GibtZDmU0SPpsdAQzv798jhRiwJJMjh7Gw3EnnwxC/3GIK0LqqcKxMd3VmLRQYtb
  VFKYJyK6LBml/iONAmCIcaLMc7CcoaalM7pmWAdyis3FFdIsYDFOQP7pWPHlAgMB
  AAGjUzBRMB0GA1UdDgQWBBSVX7d9U2nc5LgiF7CFYABdTvEn8DAfBgNVHSMEGDAW
  gBSVX7d9U2nc5LgiF7CFYABdTvEn8DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
  DQEBCwUAA4ICAQCOzQ5oPbfAAinjhGRXuBPjlkm0bfKxW3sd+ExFOopVRYlCepzg
  CQ3iiMkD2ygI6Ga1B8NhQ1kHkvZ9vISAG3R1Ew65Od/qoZ0vuCUlo9fG761Yp1i6
  w/hR1MmcE0PL2EkyVz+GwNYjq445YD0aI3m3El9VPKoJPB6VHCBmII0qcCCTpag2
  Uq77vzk4M8HYV/1lqRKH601pkaZOUul7KuS2a4GzNUNr90Fps1I0s45CE9NpyS0s
  6cDd3RITlTHoNRBTeXWy5I5lWTqeJx5lwiGc+lkXQYCY/sVOtATwTSp6EqzvS08r
  Q/4sZDxmcmGwig+afBa8Of71ndhzd5MxJHyOrhsfsGfwH6ThB8SaCliyvC/160MT
  3LuXLn6OzGLcoLMcOhlJhhy7H7DnJeellVlSc/FHVr17IKInBd7viF4Sw5NGjH/d
  q5peosB2tDkaGgOtgIMsuA7aYrilV+3ZZ3nx1Yipwju+9hU4ncCcO16OGC/bgRym
  Bg6W8b9HZ+v1dvmh7aYHKDdZCXcNX6W/bWVC/rBpo4Cq+0jJso77CQYj95EdooSQ
  kqc6bj8BpHfxU6o6nZ1Aqtfw17yPeqh6sfByn1yfLuhPBUGuU0mZQAmFGkwSP+HH
  ZqLMKxvpJe5ufLz97O8gjCh38XV6mt3VUfVEn4Yrx5M2RtEMeuEtbYMCvw==
  -----END CERTIFICATE-----

Mirror Images:

Now that we have configured all the services and configuration files we need for our OpenShift IPI deployment we can now begin the process of mirroring the images to the local respository:

# LATEST_CI_IMAGE=$(curl https://openshift-release.svc.ci.openshift.org/api/v1/releasestream/4.3.0-0.ci/latest | grep -o 'registry.svc.ci.openshift.org[^"]\+')
# export OPENSHIFT_RELEASE_IMAGE="${OPENSHIFT_RELEASE_IMAGE:-$LATEST_CI_IMAGE}"
# export GOPATH=/home/bschmaus/go
# export OCP_RELEASE=`echo $LATEST_CI_IMAGE|cut -d: -f2`
# export UPSTREAM_REPO=$LATEST_CI_IMAGE
# export LOCAL_REG='rhel8-ocp-auto.schmaustech.com:5000'
# export LOCAL_REPO='ocp4/openshift4'
# export LOCAL_SECRET_JSON="${HOME}/pull-secret.json"
# export OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE=${LOCAL_REG}/${LOCAL_REPO}:${OCP_RELEASE}
# /usr/local/bin/oc adm release mirror -a $LOCAL_SECRET_JSON --from=$UPSTREAM_REPO --to-release-image=$LOCAL_REG/$LOCAL_REPO:$OCP_RELEASE --to=$LOCAL_REG/$LOCAL_REPO

Adjust ImageContentSources in Install-Config.yaml:

Recall we original defined the install-config.yaml with a line that had RELEASEVERSION in all caps.   Since we declared the OCP_RELEASE variable in the previous steps, we are now ready to update the install-config.yaml and replace RELEASEVERSION with the proper version defined for our local repository.  The following steps initiate that change:

# NEW_RELEASE=`echo $OCP_RELEASE|sed s/.0-0.ci//g`
# sed -i s/RELEASEVERSION/$NEW_RELEASE/g /home/bschmaus/install-config.yaml

Deploying the OpenShift Cluster:

Finally after all of the steps above, we can begin the actual deployment using the commands below:


# mkdir /home/bschmaus/ocp
# cp /home/bschmaus/install-config.yaml /home/bschmaus/ocp 
# /usr/local/bin/openshift-baremetal-install --dir /home/bschmaus/ocp --log-level debug create cluster

If all the steps were followed, the cluster should successfully deploy with the exception of Metal3 container as there is an issue with this that needs to be addressed.

We can check if the cluster nodes are online with the following:

# export KUBECONFIG=/home/bschmaus/ocp/auth/kubeconfig
# oc get nodes
NAME                            STATUS   ROLES           AGE   VERSION
master-0.kni5.schmaustech.com   Ready    master,worker   10h   v1.16.2
master-1.kni5.schmaustech.com   Ready    master,worker   10h   v1.16.2
master-2.kni5.schmaustech.com   Ready    master,worker   10h   v1.16.2

We can also view all the pods to validate things are online as well:

# oc get pods --all-namespaces
NAMESPACE                                               NAME                                                              READY   STATUS                            RESTARTS   AGE
openshift-apiserver-operator                            openshift-apiserver-operator-589544b58f-hpzdj                     1/1     Running                           2          10h
openshift-apiserver                                     apiserver-gq5wv                                                   1/1     Running                           0          9h
openshift-apiserver                                     apiserver-gsds9                                                   1/1     Running                           0          9h
openshift-apiserver                                     apiserver-kqw6d                                                   1/1     Running                           0          9h
openshift-authentication-operator                       authentication-operator-58d65b5d94-7s225                          1/1     Running                           0          9h
openshift-authentication                                oauth-openshift-58c95b9459-jvnx5                                  1/1     Running                           0          9h
openshift-authentication                                oauth-openshift-58c95b9459-z9cbp                                  1/1     Running                           0          9h
openshift-cloud-credential-operator                     cloud-credential-operator-8c9748878-55n7k                         1/1     Running                           3          10h
openshift-cluster-machine-approver                      machine-approver-6485cf466b-m6r9m                                 2/2     Running                           0          10h
openshift-cluster-node-tuning-operator                  cluster-node-tuning-operator-7668d5c85c-lt8vh                     1/1     Running                           0          9h
openshift-cluster-node-tuning-operator                  tuned-fssr9                                                       1/1     Running                           0          9h
openshift-cluster-node-tuning-operator                  tuned-nzq4q                                                       1/1     Running                           0          9h
openshift-cluster-node-tuning-operator                  tuned-znl95                                                       1/1     Running                           0          9h
openshift-cluster-samples-operator                      cluster-samples-operator-66fd64c57b-swnvx                         2/2     Running                           0          9h
openshift-cluster-storage-operator                      cluster-storage-operator-698c8fc449-hzbqp                         1/1     Running                           0          9h
openshift-cluster-version                               cluster-version-operator-7449dc5b9c-2kcb8                         1/1     Running                           0          10h
openshift-console-operator                              console-operator-67bdf96b5b-lgzj4                                 1/1     Running                           0          9h
openshift-console                                       console-6df4667b8c-4bw9l                                          1/1     Running                           0          9h
openshift-console                                       console-6df4667b8c-m2pl7                                          1/1     Running                           1          9h
openshift-console                                       downloads-65fdcc888-29t6m                                         1/1     Running                           0          9h
openshift-console                                       downloads-65fdcc888-vh6tj                                         1/1     Running                           0          9h
openshift-controller-manager-operator                   openshift-controller-manager-operator-69bb4c6545-m9hf4            1/1     Running                           2          10h
openshift-controller-manager                            controller-manager-drrvv                                          1/1     Running                           0          9h
openshift-controller-manager                            controller-manager-fck8g                                          1/1     Running                           0          9h
openshift-controller-manager                            controller-manager-gnj6b                                          1/1     Running                           0          9h
openshift-dns-operator                                  dns-operator-54d6dbb59b-wrjtl                                     1/1     Running                           0          10h
openshift-dns                                           dns-default-dl2lq                                                 2/2     Running                           0          9h
openshift-dns                                           dns-default-vs8xd                                                 2/2     Running                           0          9h
openshift-dns                                           dns-default-wn4px                                                 2/2     Running                           0          9h
openshift-etcd                                          etcd-member-master-0.kni5.schmaustech.com                         2/2     Running                           0          10h
openshift-etcd                                          etcd-member-master-1.kni5.schmaustech.com                         2/2     Running                           0          10h
openshift-etcd                                          etcd-member-master-2.kni5.schmaustech.com                         2/2     Running                           0          10h
openshift-image-registry                                cluster-image-registry-operator-788f556d9d-l9hrh                  2/2     Running                           0          9h
openshift-ingress-operator                              ingress-operator-6f8d45d96f-4kw7x                                 1/1     Running                           0          9h
openshift-ingress                                       router-default-5675955655-4wqw4                                   1/1     Running                           0          9h
openshift-ingress                                       router-default-5675955655-rvjmq                                   1/1     Running                           0          9h
openshift-insights                                      insights-operator-69b4497995-ltggd                                1/1     Running                           3          10h
openshift-kni-infra                                     coredns-master-0.kni5.schmaustech.com                             1/1     Running                           0          10h
openshift-kni-infra                                     coredns-master-1.kni5.schmaustech.com                             1/1     Running                           0          10h
openshift-kni-infra                                     coredns-master-2.kni5.schmaustech.com                             1/1     Running                           0          10h
openshift-kni-infra                                     haproxy-master-0.kni5.schmaustech.com                             2/2     Running                           2          10h
openshift-kni-infra                                     haproxy-master-1.kni5.schmaustech.com                             2/2     Running                           2          10h
openshift-kni-infra                                     haproxy-master-2.kni5.schmaustech.com                             2/2     Running                           2          10h
openshift-kni-infra                                     keepalived-master-0.kni5.schmaustech.com                          2/2     Running                           0          10h
openshift-kni-infra                                     keepalived-master-1.kni5.schmaustech.com                          2/2     Running                           0          10h
openshift-kni-infra                                     keepalived-master-2.kni5.schmaustech.com                          2/2     Running                           0          10h
openshift-kni-infra                                     mdns-publisher-master-0.kni5.schmaustech.com                      1/1     Running                           0          10h
openshift-kni-infra                                     mdns-publisher-master-1.kni5.schmaustech.com                      1/1     Running                           0          10h
openshift-kni-infra                                     mdns-publisher-master-2.kni5.schmaustech.com                      1/1     Running                           0          10h
openshift-kube-apiserver-operator                       kube-apiserver-operator-79cc8666bd-sbcbq                          1/1     Running                           2          10h
openshift-kube-apiserver                                installer-2-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-2-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-2-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-3-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-5-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-5-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                installer-5-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-apiserver                                kube-apiserver-master-0.kni5.schmaustech.com                      3/3     Running                           0          9h
openshift-kube-apiserver                                kube-apiserver-master-1.kni5.schmaustech.com                      3/3     Running                           0          9h
openshift-kube-apiserver                                kube-apiserver-master-2.kni5.schmaustech.com                      3/3     Running                           1          9h
openshift-kube-apiserver                                revision-pruner-2-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-2-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-2-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-3-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-5-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-5-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-apiserver                                revision-pruner-5-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager-operator              kube-controller-manager-operator-d46bf7586-ctjcd                  1/1     Running                           2          10h
openshift-kube-controller-manager                       installer-2-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-3-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-3-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-3-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-4-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-4-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-4-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-5-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-5-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       installer-5-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-controller-manager                       kube-controller-manager-master-0.kni5.schmaustech.com             3/3     Running                           0          9h
openshift-kube-controller-manager                       kube-controller-manager-master-1.kni5.schmaustech.com             3/3     Running                           1          9h
openshift-kube-controller-manager                       kube-controller-manager-master-2.kni5.schmaustech.com             3/3     Running                           1          9h
openshift-kube-controller-manager                       revision-pruner-2-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-3-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-3-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-3-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-4-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-4-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-4-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-5-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-5-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-controller-manager                       revision-pruner-5-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler-operator                       openshift-kube-scheduler-operator-6ff9678df8-8xfnv                1/1     Running                           2          10h
openshift-kube-scheduler                                installer-2-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-3-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-5-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-5-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-5-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-6-master-0.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-6-master-1.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                installer-6-master-2.kni5.schmaustech.com                         0/1     Completed                         0          9h
openshift-kube-scheduler                                openshift-kube-scheduler-master-0.kni5.schmaustech.com            1/1     Running                           1          9h
openshift-kube-scheduler                                openshift-kube-scheduler-master-1.kni5.schmaustech.com            1/1     Running                           0          9h
openshift-kube-scheduler                                openshift-kube-scheduler-master-2.kni5.schmaustech.com            1/1     Running                           1          9h
openshift-kube-scheduler                                revision-pruner-2-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-3-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-5-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-5-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-5-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-6-master-0.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-6-master-1.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-kube-scheduler                                revision-pruner-6-master-2.kni5.schmaustech.com                   0/1     Completed                         0          9h
openshift-machine-api                                   cluster-autoscaler-operator-7f977b7c45-975p5                      2/2     Running                           0          9h
openshift-machine-api                                   machine-api-controllers-556b5ffc85-nvm9k                          4/4     Running                           0          9h
openshift-machine-api                                   machine-api-operator-8589cc9889-wp8k6                             2/2     Running                           1          10h
openshift-machine-api                                   metal3-68b9cf8bf-kmfw2                                            0/8     Init:CreateContainerConfigError   0          9h
openshift-machine-config-operator                       etcd-quorum-guard-6f6574bc9b-czhjz                                1/1     Running                           0          9h
openshift-machine-config-operator                       etcd-quorum-guard-6f6574bc9b-gd5ms                                1/1     Running                           0          9h
openshift-machine-config-operator                       etcd-quorum-guard-6f6574bc9b-zzjnb                                1/1     Running                           0          9h
openshift-machine-config-operator                       machine-config-controller-9d8c59488-dm74p                         1/1     Running                           1          9h
openshift-machine-config-operator                       machine-config-daemon-224vq                                       2/2     Running                           0          9h
openshift-machine-config-operator                       machine-config-daemon-hxhbc                                       2/2     Running                           0          9h
openshift-machine-config-operator                       machine-config-daemon-ngxbt                                       2/2     Running                           0          9h
openshift-machine-config-operator                       machine-config-operator-6cbbd79995-6b277                          1/1     Running                           1          10h
openshift-machine-config-operator                       machine-config-server-lswt8                                       1/1     Running                           0          9h
openshift-machine-config-operator                       machine-config-server-mrvln                                       1/1     Running                           0          9h
openshift-machine-config-operator                       machine-config-server-nshlv                                       1/1     Running                           0          9h
openshift-marketplace                                   certified-operators-7c44559446-w4bl2                              1/1     Running                           0          9h
openshift-marketplace                                   community-operators-64bfb7b678-7gs7q                              1/1     Running                           0          9h
openshift-marketplace                                   marketplace-operator-7776f6c9ff-mxls8                             1/1     Running                           0          9h
openshift-marketplace                                   redhat-operators-864d755755-49vh2                                 1/1     Running                           0          9h
openshift-monitoring                                    alertmanager-main-0                                               3/3     Running                           0          9h
openshift-monitoring                                    alertmanager-main-1                                               3/3     Running                           0          9h
openshift-monitoring                                    alertmanager-main-2                                               3/3     Running                           0          9h
openshift-monitoring                                    cluster-monitoring-operator-7c66dc45b4-8x6kl                      1/1     Running                           0          9h
openshift-monitoring                                    grafana-668586776b-dnfj7                                          2/2     Running                           0          9h
openshift-monitoring                                    kube-state-metrics-75df8cfbdf-bgfjv                               3/3     Running                           0          9h
openshift-monitoring                                    node-exporter-7b4s9                                               2/2     Running                           0          9h
openshift-monitoring                                    node-exporter-n459c                                               2/2     Running                           0          9h
openshift-monitoring                                    node-exporter-vvfh2                                               2/2     Running                           0          9h
openshift-monitoring                                    openshift-state-metrics-5b995c8497-2sv4m                          3/3     Running                           0          9h
openshift-monitoring                                    prometheus-adapter-bb778b866-cccw5                                1/1     Running                           0          9h
openshift-monitoring                                    prometheus-adapter-bb778b866-jxlwf                                1/1     Running                           0          9h
openshift-monitoring                                    prometheus-k8s-0                                                  7/7     Running                           1          9h
openshift-monitoring                                    prometheus-k8s-1                                                  7/7     Running                           1          9h
openshift-monitoring                                    prometheus-operator-6c4f54f97c-242ft                              1/1     Running                           0          9h
openshift-monitoring                                    thanos-querier-bf4f5dd76-bn8rb                                    4/4     Running                           0          9h
openshift-monitoring                                    thanos-querier-bf4f5dd76-lcs69                                    4/4     Running                           0          9h
openshift-multus                                        multus-admission-controller-899jw                                 1/1     Running                           1          9h
openshift-multus                                        multus-admission-controller-bwgcb                                 1/1     Running                           1          9h
openshift-multus                                        multus-admission-controller-s4rdl                                 1/1     Running                           1          9h
openshift-multus                                        multus-mzfjv                                                      1/1     Running                           0          10h
openshift-multus                                        multus-qxq9z                                                      1/1     Running                           0          10h
openshift-multus                                        multus-zfs6k                                                      1/1     Running                           0          10h
openshift-network-operator                              network-operator-55b786448c-fkt2l                                 1/1     Running                           0          10h
openshift-operator-lifecycle-manager                    catalog-operator-75b65486c-6xhwk                                  1/1     Running                           0          10h
openshift-operator-lifecycle-manager                    olm-operator-76cfbdc87f-cr4qm                                     1/1     Running                           0          10h
openshift-operator-lifecycle-manager                    packageserver-579759bb6d-44d84                                    1/1     Running                           1          9h
openshift-operator-lifecycle-manager                    packageserver-579759bb6d-x7srm                                    1/1     Running                           1          9h
openshift-sdn                                           ovs-8pmrz                                                         1/1     Running                           0          10h
openshift-sdn                                           ovs-npwxk                                                         1/1     Running                           0          10h
openshift-sdn                                           ovs-svmwk                                                         1/1     Running                           0          10h
openshift-sdn                                           sdn-controller-d8rd8                                              1/1     Running                           0          10h
openshift-sdn                                           sdn-controller-pjqxt                                              1/1     Running                           0          10h
openshift-sdn                                           sdn-controller-zr2kr                                              1/1     Running                           0          10h
openshift-sdn                                           sdn-q4w8d                                                         1/1     Running                           0          10h
openshift-sdn                                           sdn-v72dr                                                         1/1     Running                           0          10h
openshift-sdn                                           sdn-zjtc2                                                         1/1     Running                           0          10h
openshift-service-ca-operator                           service-ca-operator-748f8bff-r4g94                                1/1     Running                           1          10h
openshift-service-ca                                    apiservice-cabundle-injector-549875965f-2dlq9                     1/1     Running                           1          9h
openshift-service-ca                                    configmap-cabundle-injector-6c49fc5d79-k4mbg                      1/1     Running                           1          9h
openshift-service-ca                                    service-serving-cert-signer-5fc7c8df6f-rlp6v                      1/1     Running                           1          9h
openshift-service-catalog-apiserver-operator            openshift-service-catalog-apiserver-operator-c7c9d4494-rqmv5      1/1     Running                           0          9h
openshift-service-catalog-controller-manager-operator   openshift-service-catalog-controller-manager-operator-587bhqzmm   1/1     Running                           0          9h

Monday, July 01, 2019

Slimming Down RHEL 8 Image


I recently had a project that required the Red Hat Enterprise Linux 8 Binary DVD due to the package requirements.  This normally would not be an issue but there were further requirements that made this a bit more challenging.  Those requirements were that the image also needed to be under 4gb in size and could not be delivered via networking.   This sets up the challenge of trying to devise a way to take the DVD image which is over 6gb and par it down leaving only what is required behind.  The following will describe the process the I used to meets these requirements and while there might be other methods this was the procedure I used.

The first thing we need to do is download the RHEL 8 Binary DVD image to a running system.  Once on the system I created a directory called /rhel, mounted up the image and copied the contents to /rhel:

# mount ./rhel-8.0-x86_64-dvd.iso /mnt/ -o loop
# mkdir /rhel
# shopt -s dotglob
# cp -ai /mnt/* /rhel
# umount /mnt

The next step was to create a list of packages that I needed from an existing RHEL 8 system that was installed for the purpose of the project.   I just used a simple rpm command but formatted it just for the package name without the version.   The reason being is we just want the package name as versions might be different from image and current system due to applied errata on running system:

# rpm -qa --queryformat='%{NAME}\n' | sort -n > rhel8.lst

Now I need to get a list of packages from the RHEL 8 image and in this version there are two directories that hold packages: Appstream and BaseOS.  In my example I only needed to parse out the Appstream packages to gain enough image reduction.  So I will run the following command to grab the list:

# ls -1 /rhel/AppStream/Packages/*|xargs -n 1 basename > appstream.lst

Now that I have my two lists I needed to create some logic to be able to remove packages that I would not need and this required a comparison of the two lists.  The following script should be run from with in the /rhel directory and on successful comparison it will keep the matched packages in /rhel/AppStream/Packages.  If there is no match the package will be removed.

#!/bin/bash
while read package; do
    flag="0"
    while read rhel8; do
        if [[ "$package" =~ ^"$rhel8" ]]
        then
            flag="1"
            echo KEEP: $package $rhel8 $flag
            break
        fi
    done < rhel8.lst
    if [[ "$flag" = "0" ]]
    then
        echo REMOVE $package $rhel8 $flag
        find ./ -name $package -print -exec rm -r -f {} \;
    fi
done < appstream.lst

Now that we have removed the excessive packages from the /rhel directory structure, which if you recall is just the contents of the RHEL 8 image, we can now begin to make a new iso image.  But first since we changed the AppStream packaging we need to update the repository data.  We do this by using createrepo command:

# cd /rhel/AppStream
# createrepo  -g repodata/*comps*.xml . --update
Saving Primary metadata
Saving file lists metadata
Saving other metadata
Generating sqlite DBs
Sqlite DBs complete

At this point we can go ahead and create a new image using the following command inside /rhel:

# mkisofs -o /tmp/rhel8-slim.iso -b isolinux/isolinux.bin -c isolinux/boot.cat --no-emul-boot --boot-load-size 4 --boot-info-table -J -R -V RHEL-8-0-0-BaseOS-x86_64 .

Once the command runs the new image will be written out to /tmp/rhel8-slim.iso and if we are lucky the size is now greatly diminished:

# ls -lh /tmp/rhel8-slim.iso
-rw-r--r--. 1 root root 2.0G Jul  1 15:17 /tmp/rhel8-slim.iso

And there it is a slimmer 2gb RHEL 8 image that contains only the packages that are needed for this specific project.   Be aware this method could also be used to add custom packages to RHEL 8 as well or even script customization and/or configurations.  The flexibility is limited only to ones imagination.

Monday, June 17, 2019

Centralized vBMC Controller


In my lab I use KVM virtual machines as my "baremetal" machines for testing OpenStack and Openshift.  In both of those cases I need something that provides power management to power off/on the virtual machines during deployment phases.   This is where Virtual BMC (vBMC) comes in as a handy tool to provide that functionality.   However I really don't want to install vBMC on all of the physical hosts that were providing my virtual machines.   Thankfully as this blog will explain there is a way to run vBMC where you can centrally manage all the virtual machines.

First lets pick a host that will be our centralized vBMC controller.   This host could be a physical box or a virtual machine it does not matter.  It does however need to have SSH key authentication to any of the KVM hypervisor hosts that contain virtual machines we wish to control with vBMC.

Once I have my vBMC host I will install the required package via rpm since I did not have a repo that contained the package.  If you have a repo that does container the package I would suggest using yum install instead:

# rpm -ivh python2-virtualbmc-1.4.0-1.el7.noarch.rpm 
Preparing...                          ################################# [100%]
Updating / installing...
   1:python2-virtualbmc-1.4.0-1.el7   ################################# [100%]

Once the package is installed we should be able to run the following command to see the command line usage for vbmc when adding a host.  If you get errors about cliff.app and zmq please install these packages (python2-cliff.noarch & python2-zmq.x86_64):

# vbmc add --help
usage: vbmc add [-h] [--username USERNAME] [--password PASSWORD] [--port PORT]
                [--address ADDRESS] [--libvirt-uri LIBVIRT_URI]
                [--libvirt-sasl-username LIBVIRT_SASL_USERNAME]
                [--libvirt-sasl-password LIBVIRT_SASL_PASSWORD]
                domain_name

Create a new BMC for a virtual machine instance

positional arguments:
  domain_name           The name of the virtual machine

optional arguments:
  -h, --help            show this help message and exit
  --username USERNAME   The BMC username; defaults to "admin"
  --password PASSWORD   The BMC password; defaults to "password"
  --port PORT           Port to listen on; defaults to 623
  --address ADDRESS     The address to bind to (IPv4 and IPv6 are supported);
                        defaults to ::
  --libvirt-uri LIBVIRT_URI
                        The libvirt URI; defaults to "qemu:///system"
  --libvirt-sasl-username LIBVIRT_SASL_USERNAME
                        The libvirt SASL username; defaults to None
  --libvirt-sasl-password LIBVIRT_SASL_PASSWORD
                        The libvirt SASL password; defaults to None


Now lets try adding a virtual machine called kube-master located on a remote hypervisor host:

# vbmc add --username admin --password password --port 6230 --address 192.168.0.10 --libvirt-uri qemu+ssh://root@192.168.0.4/system kube-master

Now lets add a second virtual machine on a different hypervisor and notice I increment the port number in use as this is the unique port number that gets called when using ipmi to actually connection to the specific host we wish to power on/off or get a power status from:

# vbmc add --username admin --password password --port 6231 --address 192.168.0.10 --libvirt-uri qemu+ssh://root@192.168.0.5/system cube-vm1

Now lets start the vbmc process for them and confirm they are up and running:

# vbmc start kube-master
2019-06-17 08:48:05,649.649 6915 INFO VirtualBMC [-] Started vBMC instance for domain kube-master

# vbmc start cube-vm1
2019-06-17 14:49:39,491.491 6915 INFO VirtualBMC [-] Started vBMC instance for domain cube-vm1
# vbmc list
+-------------+---------+--------------+------+
| Domain name | Status  | Address      | Port |
+-------------+---------+--------------+------+
| cube-vm1    | running | 192.168.0.10 | 6231 |
| kube-master | running | 192.168.0.10 | 6230 |
+-------------+---------+--------------+------+

Now that we have added a few virtual machines lets validate that things are working by trying to power the hosts up and get a status. In this example we will check the power status of kube-master and power on if it is off:

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis status
System Power         : off
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis power on
Chassis Power Control: Up/On

# ipmitool -I lanplus -H192.168.0.10 -p6230 -Uadmin -Ppassword chassis status
System Power         : on
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

In the next example we will see that cube-vm1 is powered on and we should power it off:

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis status
System Power         : on
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis power off
Chassis Power Control: Down/Off

# ipmitool -I lanplus -H192.168.0.10 -p6231 -Uadmin -Ppassword chassis status
System Power         : off
Power Overload       : false
Power Interlock      : inactive
Main Power Fault     : false
Power Control Fault  : false
Power Restore Policy : always-off
Last Power Event     : 
Chassis Intrusion    : inactive
Front-Panel Lockout  : inactive
Drive Fault          : false
Cooling/Fan Fault    : false

Lets summarize what we just did.  We had a vBMC host that was ipaddress 192.168.0.10 where we installed vBMC and configured two different virtual machines kube-master and cube-vm1 which were on two completely different hypervisor guests, ip address 192.168.0.4 and 192.168.0.5 respectively.  This allowed us to remotely power manage those virtual machines without the need to install any additional software on those hypervisor hosts.

Given this flexibility one could foresee maybe in the future have a centalized vBMC container that could then in turn access any KubeVirt deployed virtual machines that are deployed within that Kubernetes cluster.  I guess its only a matter of time.

Tuesday, June 11, 2019

Metal-3 Installer Dev Scripts & Macvtap


Recently I was working with the dev-scripts from the OpenShift Metal3 project located here on github.  I had been using CI automation to run test jobs which were working perfectly in my simulated virtual baremetal environment.

However last week my CI broke due to a code change.  Looking through the changes I noticed that they introduced a discovery mechanism that relied on multicast.   Under normal circumstances when using real baremetal and not virtual baremetal this issue would not have been rendered.  But in my environment it quickly became clear that multicast traffic was not being passed.

The problem is that in order to leverage PXE booting for my virtual baremetal nodes I needed to ensure that I had a network interface that was attached to a native vlan on my physical interface since PXE traffic cannot be tagged.  The solution for this issue was to use macvtap for my virtual baremetal machines.   But as I quickly learned macvtap by default does not pass multicast.

I determined this by using tcpdump on my bootstrap node and sure enough I did not see any multicast packets when the master nodes were going through the ironic-introspection:

$ sudo tcpdump -n -i any port 5353 | grep 172.22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes

As a quick test to validate my thinking I went ahead and applied the following on the macvtap interface where the virtual bootstrap node runs:

# ip a|grep macvtap0
macvtap0@eno1: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500

# ip link set dev macvtap0 allmulticast on

# ip a|grep macvtap0
macvtap0@eno1: BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500


After setting the allmulticast on the macvtap device I went back to tcpdump again and found now my device was passing the multicast traffic I needed for host discovery:

$ sudo tcpdump -n -i any port 5353 | grep 172.22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
07:03:26.186790 IP 172.22.0.55.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:26.186807 IP 172.22.0.55.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:26.186790 IP 172.22.0.55.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:26.188884 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:26.188888 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:26.188894 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:30.659938 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:30.659951 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:30.659938 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:30.660553 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:30.660556 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:30.660561 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:33.976735 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:33.976749 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:33.976735 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal._openstack._tcp.local. TXT (QM)? baremetal._openstack._tcp.local. A (QM)? baremetal._openstack._tcp.local. (61)
07:03:33.978619 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:33.978622 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:33.978632 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal._openstack._tcp.local.:6385 0 0, (Cache flush) TXT "ipa_debug=true" "protocol=http", (Cache flush) A 172.22.0.1 (136)
07:03:36.077289 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:36.077294 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:36.077289 IP 172.22.0.58.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:36.077895 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:36.077897 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:36.077900 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:39.395298 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:39.395305 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:39.395298 IP 172.22.0.78.mdns > 224.0.0.251.mdns: 0 [3q] SRV (QM)? baremetal-introspection._openstack._tcp.local. TXT (QM)? baremetal-introspection._openstack._tcp.local. A (QM)? baremetal-introspection._openstack._tcp.local. (75)
07:03:39.396947 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:39.396951 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)
07:03:39.396956 IP 172.22.0.1.mdns > 224.0.0.251.mdns: 0*- [0q] 3/0/1 (Cache flush) SRV baremetal-introspection._openstack._tcp.local.:5050 0 0, (Cache flush) TXT "ipa_debug=1" "ipa_inspection_dhcp_all_interfaces=1" "protocol=http" "ipa_collect_lldp=1", (Cache flush) A 172.22.0.1 (203)

Further my deployment completed successfully given that multicast was being passed.  Despite the success though this is not the end of the story.  The reason is that I needed this change permanent and any reboot of the bootstrap node would cause the macvtap state to go back to the default of multicast disabled.

The solution was to ensure the following is set on the device in the bootstrap nodes kvm XML file configuration:

interface type='direct' trustGuestRxFilters='yes'

Hopefully this helps in any situation when macvtap is being used and multicast traffic is required to pass over the interface.

Monday, May 13, 2019

Deploying CSI Ceph RBD Driver on Kubernetes



The Container Storage Interface (CSI) is a standard for exposing arbitrary block and file storage storage systems to containerized workloads on Container Orchestration Systems (COs) like Kubernetes. Using CSI third-party storage providers can write and deploy plugins exposing storage systems in Kubernetes without ever having to touch the core Kubernetes code.

Ceph CSI plugins are one example that implement an interface between CSI enabled Container Orchestrator (CO) and CEPH cluster. It allows dynamically provisioning CEPH volumes and attaching them to workloads. Current implementation of Ceph CSI plugins was tested in Kubernetes environment (requires Kubernetes 1.13+), but the code does not rely on any Kubernetes specific calls and should be able to run with any CSI enabled CO.

Below is simple demonstration on how to enable Ceph RBD CSI drivers on a Kubernetes cluster.  However before we begin lets ensure that we have the following requirements already in place:


  • Kubernetes cluster v1.13+
  • allow-privileged flag enabled for both kubelet and API server
  • A Rook Ceph deployed cluster
Before we start lets confirm we have a Rook Ceph cluster running in our environment:

# kubectl get pods -n rook-ceph
NAME                                      READY   STATUS      RESTARTS   AGE
rook-ceph-mgr-a-5dbb44d7f8-78mmc          1/1     Running     2          18h
rook-ceph-mon-a-64c8d5644-qpjtf           1/1     Running     0          46h
rook-ceph-mon-b-5678cb65c7-gzcc8          1/1     Running     0          18h
rook-ceph-mon-c-799f887c56-b9fxg          1/1     Running     0          78m
rook-ceph-osd-0-5ff6f7bb5c-bc5rp          1/1     Running     0          46h
rook-ceph-osd-1-5f7c4bb454-ngsfq          1/1     Running     0          18h
rook-ceph-osd-2-7885996ffc-wnjsw          1/1     Running     0          78m
rook-ceph-osd-prepare-kube-master-grrdp   0/2     Completed   0          38m
rook-ceph-osd-prepare-kube-node1-vgdwl    0/2     Completed   0          38m
rook-ceph-osd-prepare-kube-node2-f2gq9    0/2     Completed   0          38m

First lets clone the Ceph CSI repo and change directories into which we will work from:

# git clone https://github.com/ceph/ceph-csi.git
Cloning into 'ceph-csi'...
remote: Enumerating objects: 14, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 50633 (delta 3), reused 4 (delta 0), pack-reused 50619
Receiving objects: 100% (50633/50633), 68.56 MiB | 9.67 MiB/s, done.
Resolving deltas: 100% (27537/27537), done.
# cd ceph-csi/deploy/rbd/kubernetes/

Next lets create the CSI attacher role:


# kubectl create -f csi-attacher-rbac.yaml
serviceaccount/rbd-csi-attacher created
clusterrole.rbac.authorization.k8s.io/rbd-external-attacher-runner created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-attacher-role created

Next we will create the CSI RBD attacher plugin:

# kubectl create -f csi-rbdplugin-attacher.yaml
service/csi-rbdplugin-attacher created
statefulset.apps/csi-rbdplugin-attacher created

Follow that up with creating the CSI RBD provisioner plugin:

# kubectl create -f csi-rbdplugin-provisioner.yaml
service/csi-rbdplugin-provisioner created
statefulset.apps/csi-rbdplugin-provisioner created

And finally we will create the CSI daemonset for the RBD plugin:

# kubectl create -f csi-rbdplugin.yaml
daemonset.apps/csi-rbdplugin created

At this point we will need to apply a few more role based access permissions for both the provisioner and attacher:

# kubectl apply -f csi-nodeplugin-rbac.yaml
serviceaccount/rbd-csi-nodeplugin created
clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-nodeplugin created

# kubectl apply -f csi-provisioner-rbac.yaml
serviceaccount/rbd-csi-provisioner created
clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role created
role.rbac.authorization.k8s.io/rbd-external-provisioner-cfg created
rolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role-cfg created

Now lets confirm are resources are up and operational:

# kubectl get po
NAME                          READY   STATUS    RESTARTS   AGE
csi-rbdplugin-6xlml           2/2     Running   0          36s
csi-rbdplugin-attacher-0      1/1     Running   2          5m56s
csi-rbdplugin-n98ms           2/2     Running   0          36s
csi-rbdplugin-ngrtv           2/2     Running   0          36s
csi-rbdplugin-provisioner-0   3/3     Running   0          23s

If everything looks good from the previous command lets change into the examples working directory and attempt to get the storageclass working against Ceph.  However we will need to gather a few details to ensure it works properly.

cd ceph-csi/examples/rbd

The storage class will require us to know the IP addresses of the Ceph Mons, which RBD pool we will use and of course a Ceph auth key.   I am going to use the Ceph toolbox to get that information.

# kubectl exec -it rook-ceph-tools -n rook-ceph /bin/bash

[root@rook-ceph-tools /]# ceph mon stat
e3: 3 mons at {a=10.0.0.81:6790/0,b=10.0.0.82:6790/0,c=10.0.0.83:6790/0}, election epoch 26, leader 0 a, quorum 0,1,2 a,b,c

[root@rook-ceph-tools /]# ceph osd lspools
1 rbd

[root@rook-ceph-tools /]# ceph auth get-key client.admin|base64
QVFDTDliVmNEb21IRHhBQUxXNGhmRkczTFNtcXM0ZW5VaXlTZEE9PQ==


We can take the MON addresses and client admin key and populate that in our secret.yaml file:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: default
data:
  admin: QVFDTDliVmNEb21IRHhBQUxXNGhmRkczTFNtcXM0ZW5VaXlTZEE9PQ==

We can also add the MON addresses and pool name to the storageclass.yaml:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: csi-rbd
provisioner: rbd.csi.ceph.com
parameters:
   monitors: 10.0.0.81:6790,10.0.0.82:6790,10.0.0.83:6790
   pool: rbd
   imageFormat: "2"
   imageFeatures: layering
   csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
   csi.storage.k8s.io/provisioner-secret-namespace: default
   csi.storage.k8s.io/node-publish-secret-name: csi-rbd-secret
   csi.storage.k8s.io/node-publish-secret-namespace: default
   adminid: admin
reclaimPolicy: Delete

Now that we have our files generated lets go ahead and issue the creation and validate:

# kubectl create -f secret.yaml 
secret/csi-rbd-secret created

# kubectl create -f storageclass.yaml 
storageclass.storage.k8s.io/csi-rbd created

# kubectl get storageclass
NAME      PROVISIONER        AGE
csi-rbd   rbd.csi.ceph.com   11s

Now that we have completed confiring the Ceph CSI driver and the storageclass for it lets try to provision some storage and attach it to a demo pod.  The first thing we need to do is create a block PVC so lets populate raw-block-pvc.yaml with the following:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: raw-block-pvc
spec:
  accessModes:
    - ReadWriteMany
  volumeMode: Block
  resources:
    requests:
      storage: 1Gi
  storageClassName: csi-rbd

Lets go ahead and create the PVC:

# kubectl create -f raw-block-pvc.yaml
persistentvolumeclaim/raw-block-pvc created

# kubectl get pvc
NAME            STATUS    VOLUME                                   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
raw-block-pvc   Bound     pvc-fd66b4d6-757d-11e9-8f9e-2a86e4085a59 1Gi        RWX            csi-rbd        3s

Now lets create an application to consume the PVC by first creating a template that references our PVC:

---
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-raw-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: ["tail -f /dev/null"]
      volumeDevices:
        - name: data
          devicePath: /dev/xvda
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: raw-block-pvc

Now that we have a template we can go ahead and create the application POD and if all goes well it will be up and running:

# kubectl create -f raw-block-pod.yaml
pod/pod-with-raw-block-volume created

# kubectl get pod pod-with-raw-block-volume
kubectl get pod fc-container
NAME                               READY   STATUS    RESTARTS   AGE
pod-with-raw-block-volume          1/1     Running   0          1m

Hopefully this provides an example of how to get the Ceph CSI drivers up and running in Kubernetes.

Tuesday, April 02, 2019

Deploy Rook/Ceph Cluster on Dedicated Networks


Recently a colleague of mine was trying to get Rook to deploy a Ceph cluster that used dedicated public and private networks to segment the Ceph replication traffic and the client access traffic to the OSDs of the cluster.   In a regular Ceph deployment this is rather trivial but when in the context of Kubernetes it becomes a little more complex given that Rook is deploying the cluster containers.  The following is procedure I applied to ensure my OSDs were listening on the appropriate networks.

Before we get into the steps on how to achieve this configuration lets quick take a look at the setup I used.  First I have a three node Kubernetes configuration (1 master with allowed scheduling and two workers):

# kubectl get nodes
NAME          STATUS   ROLES    AGE     VERSION
kube-master   Ready    master   2d22h   v1.14.0
kube-node1    Ready    worker   2d22h   v1.14.0
kube-node2    Ready    worker   2d22h   v1.14.0

On each of the nodes I have 3 network interfaces: eth0 on 10.0.0.0/24 (Kubernetes public), eth1 on 192.168.100.0/24 (Ceph private/cluster) & eth2 on 192.168.200.0/24 (Ceph public):

# ip a|grep eth[0-2]
2: eth0:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 10.0.0.81/24 brd 10.0.0.255 scope global noprefixroute eth0
3: eth1:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.100.81/24 brd 192.168.100.255 scope global noprefixroute eth1
4: eth2:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.200.81/24 brd 192.168.200.255 scope global noprefixroute eth2

Before we begin lets see the current vanilla pods and namespaces on the Kubernetes cluster:

# kubectl get pods --all-namespaces -o wide
NAMESPACE     NAME                                  READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
kube-system   coredns-fb8b8dccf-h6wfn               1/1     Running   0          3d    10.244.1.2   kube-node2               
kube-system   coredns-fb8b8dccf-mv7p5               1/1     Running   0          3d    10.244.0.7   kube-master              
kube-system   etcd-kube-master                      1/1     Running   0          3d    10.0.0.81    kube-master              
kube-system   kube-apiserver-kube-master            1/1     Running   0          3d    10.0.0.81    kube-master              
kube-system   kube-controller-manager-kube-master   1/1     Running   1          3d    10.0.0.81    kube-master              
kube-system   kube-flannel-ds-amd64-szhg9           1/1     Running   0          3d    10.0.0.83    kube-node2               
kube-system   kube-flannel-ds-amd64-t4fxs           1/1     Running   0          3d    10.0.0.82    kube-node1               
kube-system   kube-flannel-ds-amd64-wbsdp           1/1     Running   0          3d    10.0.0.81    kube-master              
kube-system   kube-proxy-sn7j7                      1/1     Running   0          3d    10.0.0.83    kube-node2               
kube-system   kube-proxy-wtzm5                      1/1     Running   0          3d    10.0.0.81    kube-master              
kube-system   kube-proxy-xlwd9                      1/1     Running   0          3d    10.0.0.82    kube-node1               
kube-system   kube-scheduler-kube-master            1/1     Running   1          3d    10.0.0.81    kube-master              

# kubectl get ns
NAME              STATUS   AGE
default           Active   3d
kube-node-lease   Active   3d
kube-public       Active   3d
kube-system       Active   3d

Before can deploy the cluster we need to create a configmap for the rook-ceph namespace.  This namespace is normally created when the cluster is deployed however we want specific configuration items to be incorporated into the cluster upon deployment and so to do this we will create the rook-ceph namespace and apply a configmap that we create to that namespace.

First create a configmap file that looks like the following and notice I am referencing my Ceph cluster networks.  I will save this file with an arbitrary name like config-override.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: rook-config-override
  namespace: rook-ceph
data:
  config: |
    [global]
    public network =  192.168.200.0/24
    cluster network = 192.168.100.0/24
    public addr = ""
    cluster addr = ""

Next I will create the rook-ceph namespace:

# kubectl create namespace rook-ceph
namespace/rook-ceph created

# kubectl get ns
NAME              STATUS   AGE
default           Active   3d1h
kube-node-lease   Active   3d1h
kube-public       Active   3d1h
kube-system       Active   3d1h
rook-ceph         Active   5s

Now we can apply the configmap we created to the newly created namespace and validate its there:

# kubectl create -f config-override.yaml 
configmap/rook-config-override created
# kubectl get configmap -n rook-ceph
NAME                   DATA   AGE
rook-config-override   1      66s
# kubectl describe configmap -n rook-ceph
Name:         rook-config-override
Namespace:    rook-ceph
Labels:       <none>
Annotations:  <none>

Data
====
config:
----
[global]
public network =  192.168.200.0/24
cluster network = 192.168.100.0/24
public addr = ""
cluster addr = ""

Events:  <none>


Before we actually start to do the deploy we need to update one more thing in our Rook cluster.yaml.  Inside the cluster.yaml file we need to change hostNetwork from the default of false to true:

 sed -i 's/hostNetwork: false/hostNetwork: true/g' cluster.yaml

Now we can begin the process of deploying the Rook/Ceph cluster that includes launching the operator, cluster and toolbox.   I will place sleep statements in between each command to ensure the pods are up before I run the next command.  Also note there will be an error when creating the cluster about the rook-ceph namespace already existing and this is normal:

# kubectl create -f operator.yaml
namespace/rook-ceph-system created
customresourcedefinition.apiextensions.k8s.io/cephclusters.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephfilesystems.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstores.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephobjectstoreusers.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/cephblockpools.ceph.rook.io created
customresourcedefinition.apiextensions.k8s.io/volumes.rook.io created
clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
role.rbac.authorization.k8s.io/rook-ceph-system created
clusterrole.rbac.authorization.k8s.io/rook-ceph-global created
clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
serviceaccount/rook-ceph-system created
rolebinding.rbac.authorization.k8s.io/rook-ceph-system created
clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-global created
deployment.apps/rook-ceph-operator created

# sleep 60

# kubectl create -f cluster.yaml 
serviceaccount/rook-ceph-osd created
serviceaccount/rook-ceph-mgr created
role.rbac.authorization.k8s.io/rook-ceph-osd created
role.rbac.authorization.k8s.io/rook-ceph-mgr-system created
role.rbac.authorization.k8s.io/rook-ceph-mgr created
rolebinding.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
rolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-system created
rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
cephcluster.ceph.rook.io/rook-ceph created
Error from server (AlreadyExists): error when creating "cluster.yaml": namespaces "rook-ceph" already exists

# sleep 60

# kubectl create -f toolbox.yaml 
pod/rook-ceph-tools created

Lets validate the Rook/Ceph operator, cluster and toolbox is up and running:

# kubectl get pods --all-namespaces -o wide
NAMESPACE          NAME                                      READY   STATUS      RESTARTS   AGE     IP           NODE          NOMINATED NODE   READINESS GATES
kube-system        coredns-fb8b8dccf-h6wfn                   1/1     Running     0          3d1h    10.244.1.2   kube-node2    <none>           <none>
kube-system        coredns-fb8b8dccf-mv7p5                   1/1     Running     0          3d1h    10.244.0.7   kube-master   <none>           <none>
kube-system        etcd-kube-master                          1/1     Running     0          3d1h    10.0.0.81    kube-master   <none>           <none>
kube-system        kube-apiserver-kube-master                1/1     Running     0          3d1h    10.0.0.81    kube-master   <none>           <none>
kube-system        kube-controller-manager-kube-master       1/1     Running     1          3d1h    10.0.0.81    kube-master   <none>           <none>
kube-system        kube-flannel-ds-amd64-szhg9               1/1     Running     0          3d1h    10.0.0.83    kube-node2    <none>           <none>
kube-system        kube-flannel-ds-amd64-t4fxs               1/1     Running     0          3d1h    10.0.0.82    kube-node1    <none>           <none>
kube-system        kube-flannel-ds-amd64-wbsdp               1/1     Running     0          3d1h    10.0.0.81    kube-master   <none>           <none>
kube-system        kube-proxy-sn7j7                          1/1     Running     0          3d1h    10.0.0.83    kube-node2    <none>           <none>
kube-system        kube-proxy-wtzm5                          1/1     Running     0          3d1h    10.0.0.81    kube-master   <none>           <none>
kube-system        kube-proxy-xlwd9                          1/1     Running     0          3d1h    10.0.0.82    kube-node1    <none>           <none>
kube-system        kube-scheduler-kube-master                1/1     Running     1          3d1h    10.0.0.81    kube-master   <none>           <none>
rook-ceph-system   rook-ceph-agent-55fqp                     1/1     Running     0          17m     10.0.0.83    kube-node2    <none>           <none>
rook-ceph-system   rook-ceph-agent-5v9v5                     1/1     Running     0          17m     10.0.0.81    kube-master   <none>           <none>
rook-ceph-system   rook-ceph-agent-spx29                     1/1     Running     0          17m     10.0.0.82    kube-node1    <none>           <none>
rook-ceph-system   rook-ceph-operator-57547fc866-ltp8z       1/1     Running     0          18m     10.244.2.4   kube-node1    <none>           <none>
rook-ceph-system   rook-discover-brxmt                       1/1     Running     0          17m     10.244.2.5   kube-node1    <none>           <none>
rook-ceph-system   rook-discover-hl748                       1/1     Running     0          17m     10.244.1.8   kube-node2    <none>           <none>
rook-ceph-system   rook-discover-qj5kd                       1/1     Running     0          17m     10.244.0.9   kube-master   <none>           <none>
rook-ceph          rook-ceph-mgr-a-5dbb44d7f8-vzs46          1/1     Running     0          16m     10.0.0.82    kube-node1    <none>           <none>
rook-ceph          rook-ceph-mon-a-5fb9568cb4-gvqln          1/1     Running     0          16m     10.0.0.81    kube-master   <none>           <none>
rook-ceph          rook-ceph-mon-b-b65c555bf-vz7ps           1/1     Running     0          16m     10.0.0.82    kube-node1    <none>           <none>
rook-ceph          rook-ceph-mon-c-69cf744c4d-8g4l6          1/1     Running     0          16m     10.0.0.83    kube-node2    <none>           <none>
rook-ceph          rook-ceph-osd-0-77499f547-d2vjx           1/1     Running     0          15m     10.0.0.81    kube-master   <none>           <none>
rook-ceph          rook-ceph-osd-1-698f76d786-lqn4w          1/1     Running     0          15m     10.0.0.82    kube-node1    <none>           <none>
rook-ceph          rook-ceph-osd-2-558c59d577-wfdlr          1/1     Running     0          15m     10.0.0.83    kube-node2    <none>           <none>
rook-ceph          rook-ceph-osd-prepare-kube-master-p55sw   0/2     Completed   0          15m     10.0.0.81    kube-master   <none>           <none>
rook-ceph          rook-ceph-osd-prepare-kube-node1-q7scn    0/2     Completed   0          15m     10.0.0.82    kube-node1    <none>           <none>
rook-ceph          rook-ceph-osd-prepare-kube-node2-8rm4d    0/2     Completed   0          15m     10.0.0.83    kube-node2    <none>           <none>
rook-ceph          rook-ceph-tools                           1/1     Running     0          3m24s   10.244.1.9   kube-node2    <none>           <none>

# kubectl -n rook-ceph exec -it rook-ceph-tools -- /bin/bash
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_COLLATE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_MESSAGES: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_NUMERIC: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_TIME: cannot change locale (en_US.UTF-8): No such file or directory
[root@rook-ceph-tools /]# ceph status
  cluster:
    id:     b58f2a5c-2fc7-43e7-b410-2d541e78a90e
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,b,c
    mgr: a(active)
    osd: 3 osds: 3 up, 3 in
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0  objects, 0 B
    usage:   57 GiB used, 49 GiB / 105 GiB avail
    pgs:     
 
[root@rook-ceph-tools /]# exit
exit

At this point we have a fully operational cluster but is it really using the networks for OSD public and private traffic?   Lets explore that a bit further by first running the netstat command on any node in the cluster that has an OSD pod running.  Since my cluster is small I will show all 3 nodes below:

[root@kube-master]# netstat -tulpn | grep LISTEN | grep osd
tcp        0      0 192.168.100.81:6800     0.0.0.0:*               LISTEN      29719/ceph-osd      
tcp        0      0 192.168.200.81:6800     0.0.0.0:*               LISTEN      29719/ceph-osd      
tcp        0      0 192.168.200.81:6801     0.0.0.0:*               LISTEN      29719/ceph-osd      
tcp        0      0 192.168.100.81:6801     0.0.0.0:*               LISTEN      29719/ceph-osd
[root@kube-node1]# netstat -tulpn | grep LISTEN | grep osd
tcp        0      0 192.168.100.82:6800     0.0.0.0:*               LISTEN      18770/ceph-osd      
tcp        0      0 192.168.100.82:6801     0.0.0.0:*               LISTEN      18770/ceph-osd      
tcp        0      0 192.168.200.82:6801     0.0.0.0:*               LISTEN      18770/ceph-osd      
tcp        0      0 192.168.200.82:6802     0.0.0.0:*               LISTEN      18770/ceph-osd

[root@kube-node2]# netstat -tulpn | grep LISTEN | grep osd
tcp        0      0 192.168.100.83:6800     0.0.0.0:*               LISTEN      22659/ceph-osd      
tcp        0      0 192.168.200.83:6800     0.0.0.0:*               LISTEN      22659/ceph-osd      
tcp        0      0 192.168.200.83:6801     0.0.0.0:*               LISTEN      22659/ceph-osd      
tcp        0      0 192.168.100.83:6801     0.0.0.0:*               LISTEN      22659/ceph-osd

From the above we should see the OSD processes listening on the corresponding public and private networks we configured in the configmap.   However lets further confirm by going back into the toolbox and doing a ceph osd dump:

# kubectl -n rook-ceph exec -it rook-ceph-tools -- /bin/bash
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_COLLATE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_MESSAGES: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_NUMERIC: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_TIME: cannot change locale (en_US.UTF-8): No such file or directory

[root@rook-ceph-tools]# ceph osd dump
epoch 14
fsid 05a8b767-e3e8-42aa-b792-69f479c807f7
created 2019-04-02 13:24:24.549423
modified 2019-04-02 13:25:28.441850
flags sortbitwise,recovery_deletes,purged_snapdirs
crush_version 7
full_ratio 0.95
backfillfull_ratio 0.9
nearfull_ratio 0.85
require_min_compat_client jewel
min_compat_client firefly
require_osd_release mimic
max_osd 3
osd.0 up   in  weight 1 up_from 11 up_thru 0 down_at 0 last_clean_interval [0,0) 192.168.200.81:6800/29719 192.168.100.81:6800/29719 192.168.100.81:6801/29719 192.168.200.81:6801/29719 exists,up 2feb0edf-6652-4148-8264-6ba52d04ff80
osd.1 up   in  weight 1 up_from 14 up_thru 0 down_at 0 last_clean_interval [0,0) 192.168.200.82:6801/18770 192.168.100.82:6800/18770 192.168.100.82:6801/18770 192.168.200.82:6802/18770 exists,up f8df61b4-4ac8-4705-9f97-eb09a1cc0d6c
osd.2 up   in  weight 1 up_from 14 up_thru 0 down_at 0 last_clean_interval [0,0) 192.168.200.83:6800/22659 192.168.100.83:6800/22659 192.168.100.83:6801/22659 192.168.200.83:6801/22659 exists,up db555c80-9d81-4662-aed9-4bce1c0d5d78

As you can see it can be fairly straight forward to configure Rook to deploy a Ceph cluster using segmented networks to ensure the replication traffic runs on dedicated network and does not interfere with public client performance.  Hopefully this quick demonstrate showed that.