変更した `coredns` の docker image を作ってみる
Ubuntu に Docker を install する
まずは Docker を install する。
Install Docker Engine on Ubuntu を見て作業する。
$ sudo apt-get update
$ sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
んで、動作確認がてら hello-world を実行しておきます。
$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
coredns
を make
する
つぎに GitHub - coredns/coredns を見ながら CoreDNS の環境を整えていく。
$ git clone https://github.com/coredns/coredns
$ cd coredns
のあと、golang を install してもいいんですがめんどいので、
$ docker run --rm -i -t -v $PWD:/v -w /v golang:1.17 make
でしばらく待ってると coredns という binary が完成するのでそれが楽ちんです。
コマンドの簡単な説明としては以下のとおりです。
-
--rm
は作業が終わったら conainter の削除 -
-i
-t
はまとめて-it
でもいいけどtty
使えるようにするやつ、たぶん -
-v $PWD:/v
で、$PWD
つまりcd coredns
した後のディレクトリを volume として/v
ディレクトリに mount する -
-w /v
でその/v
を working directory として run する -
golang:1.17 make
で実際にmake
される - mount して実行してるので、元の世界側に
make
した binary が落ちてる
すっごい簡単でよいですね。
Dockerfile
を編集する
次にこの coredns
を込めた docker image を作成していきます。
もともとの repository に Dockerfile
があるので、これを適当に編集していきます。
元の内容がこれで、multi-stage build を利用しているようです。
FROM debian:stable-slim
RUN apt-get update && apt-get -uy upgrade
RUN apt-get -y install ca-certificates && update-ca-certificates
FROM scratch
COPY --from=0 /etc/ssl/certs /etc/ssl/certs
ADD coredns /coredns
EXPOSE 53 53/udp
ENTRYPOINT ["/coredns"]
たぶん、こういう感じの作業のはず。
-
/etc/ssl/certs
にはルート証明書がいっぱいあるので、それを最新化するためにupdate-ca-certificates
を実行してる - コンテナ自体のサイズは最小化したいので
FROM scratch
でまっさらイメージからcoredns
の binary だけをCOPY
した docker image を用意する
で、このままだとセキュリティレベルの高い、ただしデバッグがしづらい docker image になっています。具体的には kubectl exec -it -- bash
すらできません。
$ kubectl exec coredns-xxxxxxxxx-xxxxx -n kube-system -- bash
error: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "a364eb42b1e435ff3290bb64b5249dea9f84a2a8a7ad3f8c94ea4639787c42c7": OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "bash": executable file not found in $PATH: unknown
これに関しては kubectl debug
とかの手段もあるんですが、今回は別の方法でやろうと思って進めています。
そこで、2nd stage (?) を FROM debian:stable
等に変えて、もうちょい汎用的な base image から docker image を作るように変えます。
FROM debian:stable-slim
RUN apt-get update && apt-get -uy upgrade
RUN apt-get -y install ca-certificates && update-ca-certificates
FROM debian:stable
COPY --from=0 /etc/ssl/certs /etc/ssl/certs
ADD coredns /coredns
EXPOSE 53 53/udp
ENTRYPOINT ["/coredns"]
ACR を作成し、AKS と関連付ける
ここで、別途 ACR (Azure Container Registry) を作っておきます。
クイックスタート - レジストリの作成 - Azure CLI - Azure Container Registry を参考に手順を進めればさほど難しくないです。
試してみてちょっと違う点としては、az acr login
に --expose-token
という option がいるかもしれないです。
あまり細かい点が分かってないんですが root 権限でないとうまくいかないので、sudo -s
とかで権限上げてから az login
しなおして実行しました。
$ sudo -s
# az acr login --name <acr-name> --expose-token
そのほか、AKS と ACR も接続しておきます。
こちらも Azure Container Registry と Azure Kubernetes Service を統合する があるので難しくないです。
具体的には 1 行で終わります。
$ az aks update -g <resource-group> -n <cluster-name> --attach-acr <acr-name>
build
docker image の んで、docker build
します。docker tag
をつけます。docker push
します。
$ sudo docker build -t local/custom-coredns .
$ sudo docker tag local/custom-coredns <acr-name>.azurecr.io/custom-coredns:v1
$ sudo docker push <acr-name>.azurecr.io/custom-coredns:v1
docker images
はこんな感じかと。
multi-stage build の中間の image が残るのが何か微妙よね。
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<acr-name>.azurecr.io/custom-coredns v1 1234c3187e81 15 hours ago 130MB
local/custom-coredns latest 1234c3187e81 15 hours ago 130MB
<none> <none> 6fd88635894d 15 hours ago 101MB
golang 1.17 b6bd03a3a78e 2 weeks ago 941MB
debian stable-slim b20702a8e984 2 weeks ago 80.4MB
debian stable 4c8dfa39e6ff 2 weeks ago 124MB
hello-world latest feb5d9fea6a5 7 months ago 13.3kB
ConfigMap の作成
次にその ACR から Pod を作成したいんですが、その前に coredns
用の ConfigMap
を用意しておきます。
中身は 2 つありますが、2 つめのは中身はありません。
1 つ目についてもいろいろ書いてありますが基本的には $ kubectl get cm coredns -n kube-system -o yaml
の内容を踏襲してます。
$ cat custom-coredns-configmap.yaml | sed 's/........-....-....-....-\(............\)/xxxxxxxx-xxxx-xxx
x-xxxx-\1/g'
apiVersion: v1
data:
Corefile: |
.:53 {
errors
ready
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
import custom/*.override
}
import custom/*.server
kind: ConfigMap
metadata:
annotations:
labels:
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: kube-dns
name: coredns
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
addonmanager.kubernetes.io/mode: EnsureExists
k8s-app: kube-dns
name: coredns-custom
まずはこちらを kubectl apply
します。
coredns
と coredns-custom
というのがあれば大丈夫です。
$ kubectl apply -f custom-coredns-configmap.yaml
$ kubectl get cm
NAME DATA AGE
coredns 1 14h
coredns-custom 0 14h
kube-root-ca.crt 1 18h
Pod の作成
次に pod
用の yaml を書きます。
これも kubectl get po coredns-xxxxxxxxx-xxxxx -n kube-system -o yaml
の結果を必要そうなところだけに削りまくったものです。
一番重要な修正点はここだけ。
-
.spec.containers.image
を ACR のやつに
ConfigMap
関連はたぶん以下の雰囲気のはず。
-
args
に-conf /etc/coredns/Corefile
と書いてあるのでこれが option として指定されて pod が起動する - それは
volumeMounts
でmount
されることになっている - で、それは
volumes
のところでConfigMap
で実現されている - そのために事前に
ConfigMap
を用意している
$ cat custom-coredns-pod.yaml | sed 's/........-....-....-....-\(............\)/xxxxxxxx-xxxx-xxxx-xxxx
-\1/g'
apiVersion: v1
kind: Pod
metadata:
labels:
k8s-app: kube-dns
name: custom-coredns
spec:
containers:
- args:
- -conf
- /etc/coredns/Corefile
env:
- name: KUBERNETES_PORT_443_TCP_ADDR
value: private-cl-aks-20220504-81d00f-feda6be9.xxxxxxxx-xxxx-xxxx-xxxx-c5c05e4746d6.privatelink.southeastasia.azmk8s.io
- name: KUBERNETES_PORT
value: tcp://private-cl-aks-20220504-81d00f-feda6be9.xxxxxxxx-xxxx-xxxx-xxxx-c5c05e4746d6.privatelink.southeastasia.azmk8s.io:443
- name: KUBERNETES_PORT_443_TCP
value: tcp://private-cl-aks-20220504-81d00f-feda6be9.xxxxxxxx-xxxx-xxxx-xxxx-c5c05e4746d6.privatelink.southeastasia.azmk8s.io:443
- name: KUBERNETES_SERVICE_HOST
value: private-cl-aks-20220504-81d00f-feda6be9.xxxxxxxx-xxxx-xxxx-xxxx-c5c05e4746d6.privatelink.southeastasia.azmk8s.io
image: <acr-name>.azurecr.io/custom-coredns:v1.1
imagePullPolicy: IfNotPresent
name: custom-coredns
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
volumeMounts:
- mountPath: /etc/coredns
name: config-volume
readOnly: true
- mountPath: /etc/coredns/custom
name: custom-config-volume
readOnly: true
- mountPath: /tmp
name: tmp
restartPolicy: Always
volumes:
- configMap:
defaultMode: 420
items:
- key: Corefile
path: Corefile
name: coredns
name: config-volume
- configMap:
defaultMode: 420
name: coredns-custom
optional: true
name: custom-config-volume
- emptyDir: {}
name: tmp
あとは kubectl apply
するだけですね。
$ kubectl apply -f custom-coredns-pod.yaml
この pod であれば kubectl exec -it -- bash
ができます。
$ k exec -it custom-coredns -- bash
root@custom-coredns:/#
localhost
で coredns
が DNS cache server として動いてるはずなので dig
で簡単に確認しておきましょう。
# apt-get update
# apt-get install dnsutils
# dig @localhost www.microsoft.com. +short
www.microsoft.com-c-3.edgekey.net.
www.microsoft.com-c-3.edgekey.net.globalredir.akadns.net.
e13678.dscb.akamaiedge.net.
104.83.197.169
とりあえずここまで。
Discussion