KubernetesのServiceを触って学ぶ
仕事でKubernetesを扱うことが不可欠になりつつあるので、最近重点的に学んでいる。Podの立て方は理解したが、Serviceというものが何をするのかわからなかったので、実際に動かして学んでみる。
今回使っているのは、Docker DesktopのKubernetes。Docker DesktopにはKubernetesが付属されており、 Preference
内の Kubernetes
から enable Kubernetes
を選べばよい。Docker Desktopが起動する際に、KubernetesのClusterも立ち上がるようになる。
また kubectl
コマンドも同梱されており、 初期状態では docker-desktop
というローカルのClusterを指している。
kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * docker-desktop docker-desktop docker-desktop
Serviceの役割
Serviceとは、PodやReplicaSetに対するサービスディスカバリを提供である。KubernetesのPodはそれぞれ独自のIPアドレスを持つが、Podは一度死んだら復活せず、新しく別のPodが作られIPアドレスも変わる。その場合でも、Pod間での接続を担保するためにServiceがある。
Serviceは、Podの論理的集合に対してCluserIPという仮想のIPアドレスを割り当てる。そのIPアドレスにアクセスすることで、リクエストがkube-proxyを通じて各Podに到達できるようになる。仮にPodが死んで新しくなってもClusterIPは変わらないので、相手となるPodの状態を気にせずにリクエストを送ることができる。
Serviceを作る
まずはPodとServiceを立ててみる。設定ファイルはこちらの記事のものをお借りしつつ、少し変えている。
# php-apache-pod.yaml apiVersion: v1 kind: Pod metadata: name: sample-web-pod labels: app: http-app spec: containers: - name: web-container image: php:7.0-apache ports: - name: http-port containerPort: 80 volumeMounts: - name: documentroot mountPath: /var/www/html volumes: - name: documentroot hostPath: path: /home/username/containers/web/html
#php-apache-service.yaml kind: Service apiVersion: v1 metadata: name: http-service labels: app: http-app spec: selector: app: http-app ports: - name: "service-port" protocol: "TCP" port: 8080 targetPort: http-port type: ClusterIP
Serviceの設定ファイル内では、 selector
の部分でPodのLabelを指定している。 app: http-app
というラベルは、Podの設定ファイルの metadata.labels
で指定してある。
また、 targetPort
は http-port
となっているが、これもPodの設定ファイルの中で定義した名前である。
これを使ってオブジェクトを作り、状態を見てみる。
kubectl create -f php-apache-pod.yaml pod/sample-web-pod created kubectl create -f php-apache-service.yaml service/http-service created
kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS sample-web-pod 1/1 Running 0 3h34m app=http-app kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE http-service ClusterIP 10.99.212.152 <none> 8080/TCP 6s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h41m
http-service
が作られ、ClusterIPが 10.99.212.152
になっている。Cluster内部ではこのIPアドレスを使うことでPodにアクセスできる。
それを確認するために、さらに詳しく調べてみる。
kubectl describe service http-service kubectl describe svc http-service Name: http-service Namespace: default Labels: app=http-app Annotations: <none> Selector: app=http-app Type: ClusterIP IP: 10.99.212.152 Port: service-port 8080/TCP TargetPort: http-port/TCP Endpoints: 10.1.0.5:80 Session Affinity: None Events: <none> ubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES sample-web-pod 1/1 Running 0 5h49m 10.1.0.5 docker-desktop <none> <none>
Serviceの Endpoints
が、PodのIPアドレスに等しいことがわかる。
これをふまえて、Podの中にいるApacheサーバにアクセスしてみる。ClusterIPはClusterの中からしか使えないのでどうするか迷ったが、調べるとこのClusterの中に使い捨てのPodを立ててリクエストを送るやり方が一番楽そうだった。
kubectl run testpod --image=centos:6 --restart=Never -i --rm -- curl -s http://10.99.212.152:8080/ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access / on this server.<br /> </p> <hr> <address>Apache/2.4.25 (Debian) Server at 10.99.212.152 Port 8080</address> </body></html> pod "testpod" deleted