1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ROKSクラスター外の仮想マシンにCalicoを導入してPodに直接アクセスする

Posted at

IBM CloudのManaged OpenShift(略してROKS、Red hat Openshift on ibm cloud Kubernetes Service)は、SDNドライバーにCalicoを使っているのが特徴の一つとして挙げられるが(通常はVXLANのOpenShift SDN)、Calicoの機能としてクラスター外のホストからKubernetes SDNのネットワークに参加する方法があるのを知り、試してみた。

Calico - About non-cluster hosts
https://docs.projectcalico.org/getting-started/bare-metal/about

初めに書いておくと、これが出来たところで構成上何かがうれしいという事は特にない。任意のPodにクラスター外から通信したければNodePort使えよという事である故。

ROKSクラスター

せっかくなのでVPC gen2上に作成。2ノード。
https://cloud.ibm.com/kubernetes/catalog/create?platformType=openshift

やれ標準プランのICOSが必要だの、SecurityGroupに穴を空けなきゃいかんだのをクリアしてクラスターを作成。結局image-registryのPodが証明書が違うとかエラーを吐いて起動してこない(p11-kit: couldn't complete writing file: /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt: Operation not permitted)。
安定の不安定ぶりだが、今回の検証には関係ないのでそこはスキップ。

仮想サーバー

ROKSクラスターを作った同じサブネットにVPC仮想サーバーを1台作成。CentOS7の一番小さいの。
仮想サーバー名は、例として「neighbor」。
なお、CentOS8はiptablesがなくなっているため、Calicoとは相性悪いかもと思ってやめた。今ざっとググったら動くことは動くらしいが。

OpenShiftにCluster AdminのSAを作る

仮想サーバーのCalicoがアクセスできるよう、OpenShiftクラスターにCluster Adminロールを持ったSAを作って、そのトークンを入手する。

1.ocコマンドを入手する。
https://mirror.openshift.com/pub/openshift-v4/clients/oc/

2.OpenShiftクラスターのWeb管理画面にログインし、右上の「アカウント名」>「Copy Login Command」からCLIでのログインの文字列を入手する。

3.ocコマンドでクラスターにログインする。

# oc login --token=Y4PsrZ4LSgWHMd7gnB0G-ZXuHv9Vlyi6q0P67GyAcgw --server=https://c100-e.jp-tok.containers.cloud.ibm.com:31248

4.SAを作り、cluster-adminロールを与える。

# oc create sa admin
# oc adm policy add-cluster-role-to-user cluster-admin -z admin

5.SAのトークンを入手し、kubeconfigに仕込む。

# oc get sa admin -o jsonpath='{.secrets}'
 → 「admin-token-*」のシークレット名を取得する。
# token=$(oc get secret <シークレット名>  -o jsonpath='{.data.token}' | base64 -d)
# echo $token
 → eyJhbGciOiJSUzI1NiIsIm...みたいな、10行ぐらいのランダム文字列が表示
# server=$(grep -o 'https://.*$' .kube/config | head -n 1)
# cat > .kube/config << EOF
apiVersion: v1
kind: Config
preferences: {}
clusters:
- name: cluster
  cluster:
    server: ${server}
contexts:
- name: default
  context:
    cluster: cluster
    namespace: default
    user: admin
current-context: default
users:
- name: admin
  user:
    token: ${token}
EOF

作ったら、kubeconfigが有効なことを確かめる。

# oc get svc

(実行結果)
[root@neighbor ~]# oc get svc
NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP                            PORT(S)    AGE
kubernetes            ClusterIP      172.21.0.1       <none>                                 443/TCP    6h55m
openshift             ExternalName   <none>           kubernetes.default.svc.cluster.local   <none>     6h27m
openshift-apiserver   ClusterIP      172.21.34.217    <none>                                 443/TCP    6h55m

Calico Felixをインストールする

コンテナ版を導入する必要がある(記事作成時点では)。

1.Dockerをインストールする。

# sudo yum install -y yum-utils
# sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
# sudo yum install docker-ce docker-ce-cli containerd.io
# sudo systemctl start docker

2.OpenShiftクラスターに疑似ノードを作る。
(参考)https://github.com/projectcalico/calico/issues/3551

oc create -f - <<EOF
apiVersion: v1
kind: Node
metadata:
  name: neighbor
EOF

3.OpenShiftクラスターで動いているCalicoのバージョンを確認する。

# oc get ds -n calico-system calico-node -o jsonpath='{.spec.template.spec.containers[0].image}'
 → ~calico/node:v3.16.5

4.Calicoを起動する。
起動前に、その時点のroute状態を確認してもいい。

# route -n

(実行結果)
[root@neighbor ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.244.64.1     0.0.0.0         UG    0      0        0 eth0
10.244.64.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

起動する。

# docker run -d --rm --net=host --privileged \
  --name="calico-node" \
  -e DATASTORE_TYPE="kubernetes" \
  -e KUBECONFIG="/tmp/kube_config" \
  -e CALICO_NODENAME="neighbor" \
  -e CALICO_NETWORKING_BACKEND="bird" \
  -v /var/log/calico:/var/log/calico \
  -v /run/docker/plugins:/run/docker/plugins \
  -v /lib/modules:/lib/modules \
  -v /var/run/calico:/var/run/calico \
  -v /etc/pki:/pki \
  -v /root/.kube/config:/tmp/kube_config \
  calico/node:v3.16.5

起動後、routeに以下「172.17.9.64 10.244.64.4」、「172.17.43.128 10.244.64.5」、「172.17.55.192 0.0.0.0」の3つの行が追加されていれば成功である。

[root@neighbor ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.244.64.1     0.0.0.0         UG    0      0        0 eth0
10.244.64.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.17.9.64     10.244.64.4     255.255.255.192 UG    0      0        0 eth0
172.17.43.128   10.244.64.5     255.255.255.192 UG    0      0        0 eth0
172.17.55.192   0.0.0.0         255.255.255.192 U     0      0        0 *

また、例えばクラスターのcalico-nodeに接続しても、仮想サーバーのアドレス(ここでは10.244.64.8)がルーターとしてテーブルに追加されているのを確認できるはずである。

# oc exec -it -n calico-system calico-node-g4dpg bash
# ip route
...
172.17.55.192/26 via 10.244.64.8 dev eth0 proto bird
...

Podにアクセスしてみる

oc get pod -o wideコマンドでPodを確認すると、表示されるPodのIPアドレスは172.17.9.64、172.17.43.128のいずれかのサブネットに所属しているはずである。
それらPodのIPアドレスに、仮想サーバーから直接アクセスできることを確認する。

例えば、、Prometheusとか?

# ipaddr=$(oc get pod -n openshift-monitoring prometheus-k8s-0 -o jsonpath='{.status.podIP}')
# echo $ipaddr
 → 172.17.9.98
# start=$(date -d yesterday +%s)
# end=$(date +%s)
# curl -k -H "Authorization:Bearer $token" \
https://${ipaddr}:9091/api/v1/query_range \
--data-urlencode "start=$start" \
--data-urlencode "end=$end" \
--data-urlencode "step=30" \
--data-urlencode 'query=sum(rate(container_cpu_usage_seconds_total{namespace="default"}[5m])) by (pod_name) * 100'

{"status":"success","data":...といった、100行ぐらいのデータが出力されれば成功である。

ついでに

最初に書いたが、これで何が嬉しいというのも実のところ特には無く、例えば上記のPrometheusはデフォルトでrouteが公開されているし、よしんば無かったとしても以下のようなNodePortを追加してそこからアクセスすれば良いのである。

# oc expose pod -n openshift-monitoring prometheus-k8s-0 --type=NodePort --port 9091
# oc get node
# ipaddr=<適当なノードのIPアドレス>
# nodeport=$(oc get svc -n openshift-monitoring prometheus-k8s-0 -o jsonpath='{.spec.ports[0].nodePort}')
# curl -k -H "Authorization:Bearer $token" \
https://${ipaddr}:${nodeport}/api/v1/query_range \
--data-urlencode "start=$start" \
--data-urlencode "end=$end" \
--data-urlencode "step=30" \
--data-urlencode 'query=sum(rate(container_cpu_usage_seconds_total{namespace="default"}[5m])) by (pod_name) * 100'
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?