hirano00o's blog

技術的な記録、日常の記録

Kubernetes The Hard Way for RaspberryPi 5 〜kubeletデプロイから完了まで〜

Raspberry Pi 5を利用しておうちKubernetes(v1.29)を構築する。今回が最後で、kubeletkube-proxyCoreDNSのデプロイを行う。

前回はetcdkube-apiserverkube-controller-managerkube-schedulerのデプロイまで実施した。 hirano00o.hateblo.jp

CyberAgentのリポジトリ を参考にしつつ、v1.29に合わせて手順やスクリプトを一部改変している。

Hardwayの手順は下記の通り。

No 項目 構築対象 備考
1 証明書の作成 rs01
2 Kubeconfigの生成 rs01
3 etcdのデプロイ rs01
4 kube-apiserverのデプロイ rs01
5 kube-controller-managerのデプロイ rs01
6 kube-schedulerのデプロイ rs01
7 kubeletのデプロイ rs01
rs02
rs03
ここから再開
8 kube-proxyのデプロイ rs01
rs02
rs03
9 ルーティング追加 rs01
rs02
rs03
10 kubeletのkube-apiserver認証とRBAC設定 rs01
11 CoreDNSのデプロイ rs01

改めてサブネットやホスト名等を下記に示しておく。

名前 サブネット
自宅 10.105.136.0/22
Pod 10.0.0.0/16
ClusterIP用 10.10.0.0/24
ホスト名 IPアドレス Pod用サブネット ログインユーザ 備考
rs01 10.105.138.201 10.0.1.0/24 hirano00o Master, Worker兼用
rs02 10.105.138.202 10.0.2.0/24 hirano00o Worker
rs03 10.105.138.203 10.0.3.0/24 hirano00o Worker

kubeletのデプロイ

kubeletはPodSpecsに従ってPodやコンテナの作成、開始、停止などの管理をする。またノードのリソース監視も行う。kube-schedulerはこのリソース状況を利用し、スケジューリングされてないPodを最適なノードに配置する。 containerdruncを利用する。Kuberbetes v1.24以降、CNIはkubeletの管理範囲外となった。containerdでCNIを管理する。

ここからは各ノードで同じ作業を行う。

cd
sudo mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin \
  /var/lib/kubelet \
  /var/lib/kubernetes \
  /etc/containerd

sudo cp -ai ${HOSTNAME}-key.pem ${HOSTNAME}.pem /var/lib/kubelet/
sudo cp -ai ${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig
sudo cp -ai ca.pem /var/lib/kubernetes/ # Masterは配置済みなのでスキップ

mkdir -p ~/ws/k8s/ && cd $_
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubelet"
curl -LO https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-arm64.tar.gz 
curl -LO https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-arm64-v1.4.0.tgz

tar zxf crictl-v1.29.0-linux-arm64.tar.gz
sudo tar zxvf cni-plugins-linux-arm64-v1.4.0.tgz -C /opt/cni/bin/
chmod +x crictl kubelet
sudo mv crictl kubelet /usr/local/bin/
kubelet --version
# Kubernetes v1.29.2
crictl --version
# crictl version v1.29.0

containerd, runc, kubeletの設定を行う。

CNIでプラグインを使う場合はv1.0以上が推奨なので 1.0.0 に変更する(1.1以上は未サポート)。 参考: https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/

また、/run/systemd/resolve/resolv.conf が存在しないので /etc/resolv.conf に変更する。(systemd-resolved がデフォルトではインストールされていないため)

最新のkubeletを利用しているため、元の手順からは削除されているフラグ等がある。

  • --network-plugin
  • --container-runtime
  • --image-pull-progress-deadline
  • --container-runtime-endpointKubeletConfiguration へ移動、ソケットファイルのパスも変更

またKubeletConfigurationに下記を追加している。

containerd --version
# containerd github.com/containerd/containerd 1.6.20~ds1 1.6.20~ds1-1+b1
runc --version
# runc version 1.1.5+ds1
# commit: 1.1.5+ds1-1+deb12u1
# spec: 1.0.2-dev
# go: go1.19.8
# libseccomp: 2.5.4

POD_CIDR="10.0.1.0/24" # rs02は 10.0.2.0/24, rs03は 10.0.3.0/24
cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf
{
    "cniVersion": "1.0.0",
    "name": "bridge",
    "type": "bridge",
    "bridge": "cnio0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "ranges": [
          [{"subnet": "${POD_CIDR}"}]
        ],
        "routes": [{"dst": "0.0.0.0/0"}]
    }
}
EOF

cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
{
    "cniVersion": "1.0.0",
    "name": "lo",
    "type": "loopback"
}
EOF

containerd config default | sudo tee /etc/containerd/config.toml
sudo vi /etc/containerd/config.toml
# 下記のようにSystemdCgroupをtrueに変更する
   [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
     SystemdCgroup = true
sudo systemctl restart containerd

CLUSTER_DNS_ADDRESS="10.10.0.10"
cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
  x509:
    clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
  mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
  - "${CLUSTER_DNS_ADDRESS}"
podCIDR: "${POD_CIDR}"
resolvConf: "/etc/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
containerRuntimeEndpoint: "unix:///run/containerd/containerd.sock"
cgroupDriver: systemd
EOF

cat <<EOF | sudo tee /etc/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
  --config=/var/lib/kubelet/kubelet-config.yaml \\
  --kubeconfig=/var/lib/kubelet/kubeconfig \\
  --register-node=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start kubelet
sudo systemctl status kubelet
sudo systemctl enable kubelet

kube-proxyのデプロイ

kube-proxyは各ノードのネットワーク設定を行い、クラスタ内部や外部ネットワークからPodへの通信が可能になる。

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kube-proxy"
chmod +x kube-proxy
sudo mv kube-proxy /usr/local/bin/
sudo mkdir -p /var/lib/kube-proxy
sudo mv ~/kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig

POD_NETWORK="10.0.0.0/16"
cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "${POD_NETWORK}"
EOF

cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
  --config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start kube-proxy
sudo systemctl status kube-proxy
sudo systemctl enable kube-proxy

ルーティング追加

各NodeからPod用NWに到達させるためにルーティングを追加する。

# Master node(rs01)
sudo nmcli connection modify eth0 +ipv4.routes "10.0.2.0/24 10.105.138.202"
sudo nmcli connection modify eth0 +ipv4.routes "10.0.3.0/24 10.105.138.203"

# Worker node1(rs02)
sudo nmcli connection modify eth0 +ipv4.routes "10.0.1.0/24 10.105.138.201"
sudo nmcli connection modify eth0 +ipv4.routes "10.0.3.0/24 10.105.138.203"

# Worker node2(rs03)
sudo nmcli connection modify eth0 +ipv4.routes "10.0.1.0/24 10.105.138.201"
sudo nmcli connection modify eth0 +ipv4.routes "10.0.2.0/24 10.105.138.202"

sudo reboot
# 投入したルーティングが追加されているか確認
ip route

kubeletのkube-apiserver認証とRBAC設定

ここからはMaster nodeのみで行う。kube-apiserverが各ノードのkubeletにアクセスできるように設定する。

cd ~/ws/k8s/
cat <<EOF | kubectl apply --kubeconfig kubeconfig/admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
    verbs:
      - "*"
EOF

cat <<EOF | kubectl apply --kubeconfig kubeconfig/admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetes
EOF

Nodeの動作確認

ノードを認識できているか確認する。

kubectl get node
# NAME   STATUS   ROLES    AGE     VERSION
# rs01   Ready    <none>   4m28s   v1.29.2
# rs02   Ready    <none>   4m28s   v1.29.2
# rs03   Ready    <none>   4m28s   v1.29.2

CoreDNSのデプロイ

クラスタ内部で名前解決を行うために実施する。

cd ~/ws/k8s/
vi coredns-1.11.1.yaml # 下記マニフェスト参照
kubectl apply -f coredns-1.11.1.yaml

coredns-1.11.1.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: coredns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  - services
  - pods
  - namespaces
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
- apiGroups:
  - "discovery.k8s.io"
  resources:
  - endpointslices
  verbs:
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:coredns
subjects:
- kind: ServiceAccount
  name: coredns
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: "CoreDNS"
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: coredns
        image: coredns/coredns:1.11.1
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.10.0.10
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP

マニフェストでやっていることは下記の通り。

  • kube-system namespaceにcorednsのサービスアカウントを作成
    • 権限( endpointslices )が足りてないようだったので追加した
  • system:corednsのクラスタロールを作成
  • corednsのサービスアカウントにsystem:corednsの権限を付与
  • DNSの設定
  • CoreDNSのデプロイ
  • サービスとして公開
    • clusterIPは環境に合わせて書き換えること

デプロイしたらDNSが動いているか確認する。動いてなさそうだったらログを確認する(kubectl logs -f -n kube-system <ポッド名>)。

# STATUSがRunningでもREADYじゃなかったらdescribeでEventを見たり、ログを確認する
kubectl get po -n kube-system -o wide
# NAME                       READY   STATUS    RESTARTS   AGE     IP          NODE   NOMINATED NODE   READINESS GATES
# coredns-5774666f6d-wntvb   1/1     Running   0          3h44m   10.0.3.8    rs03   <none>           <none>
# coredns-5774666f6d-xj686   1/1     Running   0          3h44m   10.0.2.15   rs02   <none>           <none>

kubectl describe po -n kube-system $(kubectl get po -n kube-system --output=jsonpath='{.items[0].metadata.name}')
# Name:                 coredns-5774666f6d-wntvb
# Namespace:            kube-system
# Priority:             2000000000
# Priority Class Name:  system-cluster-critical
# Service Account:      coredns
# Node:                 rs03/10.105.138.203
# ...
# Events:                      <none>

kubectl logs -f -n kube-system $(kubectl get po -n kube-system --output=jsonpath='{.items[0].metadata.name}')
# ...

Podから名前解決できるか確認する。

# 一旦kubernetes.default.svc.cluster.localは解決できてるので良しとする
kubectl run test --image busybox:1.36 --restart Never -it --rm -- nslookup kubernetes
# If you don't see a command prompt, try pressing enter.
# warning: couldn't attach to pod/test, falling back to streaming logs: unable to upgrade connection: container test not found in pod test_default
# Server:      10.10.0.10
# Address: 10.10.0.10:53
# 
# ** server can't find kubernetes.cluster.local: NXDOMAIN
# 
# ** server can't find kubernetes.cluster.local: NXDOMAIN
# 
# ** server can't find kubernetes.svc.cluster.local: NXDOMAIN
# 
# ** server can't find kubernetes.svc.cluster.local: NXDOMAIN
# 
# 
# Name:    kubernetes.default.svc.cluster.local
# Address: 10.10.0.1
# 
# pod "test" deleted
# pod default/test terminated (Error)

kubectl run test --image busybox:1.36 --restart Never -it --rm -- nslookup google.com
# Server:      10.10.0.10
# Address: 10.10.0.10:53
# 
# Name:    google.com
# Address: 172.217.175.46
# 
# Name:    google.com
# Address: 2404:6800:4004:820::200e
# 
# pod "test" deleted

最終確認

暗号化されたsecretが保存されることを確認する。

kubectl create secret generic kubernetes-the-hard-way \
  --from-literal="mykey=mydata"
  
sudo ETCDCTL_API=3 etcdctl get \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/etcd/ca.pem \
  --cert=/etc/etcd/kubernetes.pem \
  --key=/etc/etcd/kubernetes-key.pem \
  /registry/secrets/default/kubernetes-the-hard-way | hexdump -C
# 00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
# 00000010  73 2f 64 65 66 61 75 6c  74 2f 6b 75 62 65 72 6e  |s/default/kubern|
# 00000020  65 74 65 73 2d 74 68 65  2d 68 61 72 64 2d 77 61  |etes-the-hard-wa|
# 00000030  79 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |y.k8s:enc:aescbc|
# 00000040  3a 76 31 3a 6b 65 79 31  3a 06 2d 76 2e 57 e4 c7  |:v1:key1:.-v.W..|
# 00000050  84 a6 ee 1f 86 8d 46 af  b8 81 98 ec 36 a6 01 89  |......F.....6...|
# 00000060  19 58 d5 4d 3a 0c c6 f1  3f 30 0f 7f aa 5d 43 80  |.X.M:...?0...]C.|
# 00000070  3a eb fb 97 0e 7c 92 4b  39 21 5b a0 80 12 ea 41  |:....|.K9![....A|
# 00000080  98 bb 81 4c 76 d7 e3 9d  2e 98 b5 83 54 b0 c4 b6  |...Lv.......T...|
# 00000090  b7 34 85 6f fa 79 16 1f  4d 33 de a8 d0 d9 b4 1a  |.4.o.y..M3......|
# 000000a0  0a b8 55 d4 d8 39 cb e6  3e ec 9a 34 4d 31 9f a3  |..U..9..>..4M1..|
# 000000b0  33 dd ef 4d 20 23 da 17  67 e4 a7 24 f5 39 e8 d3  |3..M #..g..$.9..|
# 000000c0  c2 59 32 88 93 60 d1 3e  dc ff 47 4f 9a 63 4e b0  |.Y2..`.>..GO.cN.|
# 000000d0  fe 8d 27 1c dd 71 de f2  62 43 42 65 cb 88 80 12  |..'..q..bCBe....|
# 000000e0  03 c6 56 b1 22 bd 17 d3  7a 12 46 91 10 52 5e 79  |..V."...z.F..R^y|
# 000000f0  09 c7 a0 79 6f 80 f4 58  a1 c3 38 5e 75 84 79 b0  |...yo..X..8^u.y.|
# 00000100  70 a7 06 32 d0 6a ce 0f  42 ea 27 c7 ce 0a 6d 3f  |p..2.j..B.'...m?|
# 00000110  19 f2 fd a9 55 87 db 72  1b 06 5b 42 42 b2 cb ae  |....U..r..[BB...|
# 00000120  14 be 8a e4 24 dc d5 ee  8d cd 50 ff 7a a6 bc 63  |....$.....P.z..c|
# 00000130  6d 25 77 2e 0e 87 cf 59  3e 5f e6 4e 61 49 c9 1b  |m%w....Y>_.NaI..|
# 00000140  ea e6 b0 91 4b 73 16 65  6b 87 7e e4 02 55 6b aa  |....Ks.ek.~..Uk.|
# 00000150  77 26 e0 90 b2 19 88 c5  75 0a                    |w&......u.|
# 0000015a

kubectl delete secret kubernetes-the-hard-way
# secret "kubernetes-the-hard-way" deleted

nginxを動かし、いくつか確認する。

kubectl create deployment nginx --image=nginx
kubectl get pods -o wide
# NAME                     READY   STATUS    RESTARTS   AGE    IP          NODE   NOMINATED NODE   READINESS GATES
# nginx-7854ff8877-q5lws   1/1     Running   0          2m7s   10.0.1.13   rs01   <none>           <none>

ポートフォワーディングを確認する。

POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8081:80
# Forwarding from 127.0.0.1:8081 -> 80
# Forwarding from [::1]:8081 -> 80

# 別ターミナルから操作
curl --head http://127.0.0.1:8081
# HTTP/1.1 200 OK
# Server: nginx/1.25.4
# Date: Tue, 27 Feb 2024 10:38:25 GMT
# Content-Type: text/html
# Content-Length: 615
# Last-Modified: Wed, 14 Feb 2024 16:03:00 GMT
# Connection: keep-alive
# ETag: "65cce434-267"
# Accept-Ranges: bytes

ログを確認する。

kubectl logs $POD_NAME
# ...
# 127.0.0.1 - - [27/Feb/2024:10:38:25 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.88.1" "-"
# ...

Pod上でコマンドを実行する。

kubectl exec -ti $POD_NAME -- nginx -v
# nginx version: nginx/1.25.4

NodePortを通じてアクセスできることを確認する。

kubectl expose deployment nginx --port 80 --type NodePort
# service/nginx exposed
kubectl get svc
# NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
# kubernetes   ClusterIP   10.10.0.1     <none>        443/TCP        3d21h
# nginx        NodePort    10.10.0.233   <none>        80:32663/TCP   7s
curl -I http://10.105.138.201:32663
# HTTP/1.1 200 OK
# Server: nginx/1.25.4
# Date: Tue, 27 Feb 2024 10:45:20 GMT
# Content-Type: text/html
# Content-Length: 615
# Last-Modified: Wed, 14 Feb 2024 16:03:00 GMT
# Connection: keep-alive
# ETag: "65cce434-267"
# Accept-Ranges: bytes

curl -I http://10.105.138.202:32663
# HTTP/1.1 200 OK
# Server: nginx/1.25.4
# Date: Tue, 27 Feb 2024 10:45:23 GMT
# Content-Type: text/html
# Content-Length: 615
# Last-Modified: Wed, 14 Feb 2024 16:03:00 GMT
# Connection: keep-alive
# ETag: "65cce434-267"
# Accept-Ranges: bytes

curl -I http://10.105.138.203:32663
# HTTP/1.1 200 OK
# Server: nginx/1.25.4
# Date: Tue, 27 Feb 2024 10:45:27 GMT
# Content-Type: text/html
# Content-Length: 615
# Last-Modified: Wed, 14 Feb 2024 16:03:00 GMT
# Connection: keep-alive
# ETag: "65cce434-267"
# Accept-Ranges: bytes

オプション補完とエイリアス設定

cat <<EOF >> ~/.bashrc
source <(kubectl completion bash)
alias k='kubectl'
complete -o default -F __start_kubectl k
EOF
source ~/.bashrc

終わりに

Raspberry PiでKubernetesクラスタを構築した。この後は、CNIとkube-proxyCiliumに入れ替えてみようと思う。また、外部からデプロイしたアプリケーションにアクセスできるようにするために、cloudflaredを利用するなど、やることは多い。

最終的には、パブリッククラウドの無料枠で動かしているサービスを移行して、すべて自宅でホストできるようにしたい。