見出し画像

Kubernetes動かしてみた

1. Kubernetesを使うと何がうれしいの?

コンテナ仮想化「Docker」ではコンテナの作成やコンテナ内でファイルシステムとして使われるイメージの作成および管理、コンテナの実行といったことは出来るけど、ネットワークのルーティングや複数コンテナの連携、管理する機能などは提供されていない。海にそれぞれ浮かぶ各コンテナをまとめて管理してあげるのがKubernetes。

Kubernetesでは以下のことが可能となる。

・コンテナに割り振られるIPアドレスの管理
・コンテナ間のネットワークルーティング管理※
・複数のコンテナを利用した負荷分散
・コンテナに割り当てるストレージの管理
・コンテナの監視
・コンテナのグルーピング

※kubernetesを利用することで複数台のnodeから構成されるクラスタ環境において、どのnode上でコンテナが稼動しているのかを意識せずにコンテナとIPアドレスを紐付けることが可能。

2. Kubernetes 動かしてみた

1) Vagrantで Kubernetesクラスターを構築

以下の Vagrantfile を作って、vagrant up で k8s_master とk8s_nodeを起動

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'net/http'
require 'uri'

Vagrant.configure("2") do |config|
  config.vm.define "k8s_master" do |k8s_master|
  	$script = <<-'SCRIPT'
    yum update
    yum -y install etcd kubernetes flannel
      SCRIPT

    k8s_master.vm.box = "bento/centos-7.2"
    k8s_master.vm.provision "shell" , inline: $script
    k8s_master.vm.hostname = "k8s-master"
    k8s_master.vm.network "private_network", ip: "192.168.17.10"
    k8s_master.vm.network "forwarded_port", guest: 80, host:8888

  config.vm.define "k8s_node" do |k8s_node|
  	$script = <<-'SCRIPT'
    yum update
    yum -y install kubernetes docker flannel
      SCRIPT

    k8s_node.vm.box = "bento/centos-7.2"
    k8s_node.vm.provision "shell" , inline: $script
    k8s_node.vm.hostname = "k8s-node"
    k8s_node.vm.network "private_network", ip: "192.168.17.20"
    k8s_node.vm.network "forwarded_port", guest: 80, host:8889

  end

config.push.define "local-exec" do |push|
  # Need to change NETCONF ...
  push.inline = <<-"SCRIPT"
  curl -u vagrant:vagrant http://localhost:2224/restconf/api/running/native/interface/GigabitEthernet/2 -X PUT -H 'Content-type: application/vnd.yang.data+json' --data @set_if.json
    SCRIPT
end

end

2) Master設定
こちらを 参考に設定。
sudo systemctl start kubelet でエラーになったので、SELinuxを無効にしたらうまくいった。※Node設定でも同じように SELinuxは無効にした。

3) Node設定
https://qiita.com/Esfahan/items/256fdb78e6a40b7c3e1f
こちらを参考に設定

Master/Node設定が終わったら master側で nodeが認識できていることを確認。

[vagrant@k8s-master ~]$ kubectl get node
NAME      STATUS    AGE
master    Ready     1d
node01    Ready     1d

4) Pod作成
yamlファイルを作る

[vagrant@k8s-master ~]$ cat pod-httpd.yaml
apiVersion: v1
kind: Pod
metadata:
  name: httpd
  labels:
    app: httpd
spec:
  containers:
  - name: httpd
    image: httpd
    ports:
    - containerPort: 80

Pod起動

kubectl create -f pod-httpd.yaml

しかし、失敗。

Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
[vagrant@k8s-master ~]$ kubectl describe pod httpd
Name:       httpd
Namespace:  default
Node:       node01/192.168.17.20
Start Time: Sat, 24 Nov 2018 13:37:32 +0000
Labels:     app=httpd
Status:     Pending
IP:
Controllers:    <none>
Containers:
  httpd:
    Container ID:
    Image:      httpd
    Image ID:
    Port:       80/TCP
    State:      Waiting
      Reason:       ContainerCreating
    Ready:      False
    Restart Count:  0
    Volume Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-lm7g7 (ro)
    Environment Variables:  <none>
Conditions:
  Type      Status
  Initialized   True
  Ready     False
  PodScheduled  True
Volumes:
  default-token-lm7g7:
    Type:   Secret (a volume populated by a Secret)
    SecretName: default-token-lm7g7
QoS Class:  BestEffort
Tolerations:    <none>
Events:
  FirstSeen LastSeen    Count   From            SubObjectPath   Type        Reason      Message
  --------- --------    -----   ----            -------------   --------    ------      -------
  2d        5m      22  {kubelet node01}            Warning     FailedSync  Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request.  details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

  2d    14s 185 {kubelet node01}        Warning FailedSync  Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""


https://qiita.com/kamaboko123/items/80f3161c5d781dfc7700 
この記事を参考に、Master/Node両方で rhsmをインストールしたが、これでも解決しないので、最終的には以下の記事を参考に、 証明書設定をコメントアウトして解決した。

https://unix.stackexchange.com/questions/400938/unable-to-pull-images-in-kubernetes

I solved it commenting the line :
KUBELET_POD_INFRA_CONTAINER="--pod-infra-containerimage=registry.access.redhat.com/rhel7/pod-infrastructure:latest" in /etc/kubernetes/kubelet on each of my slaves

Pod完成

[vagrant@k8s-master ~]$ kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
httpd     1/1       Running   0          21s
[vagrant@k8s-master ~]$ kubectl describe pod httpd
Name:       httpd
Namespace:  default
Node:       node01/192.168.17.20
Start Time: Tue, 27 Nov 2018 07:13:09 +0000
Labels:     app=httpd
Status:     Running
IP:     172.17.40.2
Controllers:    <none>
Containers:
  httpd:
    Container ID:   docker://47663b8a6d882617b3caff81536220159ad7e9a2b5179f1dc5c05bfb7446520d
    Image:      httpd
    Image ID:       docker-pullable://docker.io/httpd@sha256:9753aabc6b0b8cd0a39733ec13b7aad59e51069ce96d63c6617746272752738e
    Port:       80/TCP
    State:      Running
      Started:      Tue, 27 Nov 2018 07:13:23 +0000
    Ready:      True
    Restart Count:  0
    Volume Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-lm7g7 (ro)
    Environment Variables:  <none>
Conditions:
  Type      Status
  Initialized   True
  Ready     True
  PodScheduled  True
Volumes:
  default-token-lm7g7:
    Type:   Secret (a volume populated by a Secret)
    SecretName: default-token-lm7g7
QoS Class:  BestEffort
Tolerations:    <none>
Events:
  FirstSeen LastSeen    Count   From            SubObjectPath       Type        Reason          Message
  --------- --------    -----   ----            -------------       --------    ------          -------
  26s       26s     1   {default-scheduler }                Normal      Scheduled       Successfully assigned httpd to node01
  23s       23s     1   {kubelet node01}    spec.containers{httpd}  Normal      Pulling         pulling image "httpd"
  24s       13s     2   {kubelet node01}                Warning     MissingClusterDNS   kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  13s       13s     1   {kubelet node01}    spec.containers{httpd}  Normal      Pulled          Successfully pulled image "httpd"
  12s       12s     1   {kubelet node01}    spec.containers{httpd}  Normal      Created         Created container with docker id 47663b8a6d88; Security:[seccomp=unconfined]
  12s       12s     1   {kubelet node01}    spec.containers{httpd}  Normal      Started         Started container with docker id 47663b8a6d88

curlで pod に振られた IP 172.17.40.2 にアクセスしてみる。

[vagrant@k8s-node ~]$ curl 172.17.40.2
<html><body><h1>It works!</h1></body></html>

(option指定で) yaml形式でpodの詳細を表示

[vagrant@k8s-master ~]$ kubectl get pod httpd -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: 2018-11-27T07:13:09Z
  labels:
    app: httpd
  name: httpd
  namespace: default
  resourceVersion: "14419"
  selfLink: /api/v1/namespaces/default/pods/httpd
  uid: e523b326-f213-11e8-b742-0800275ae9e7
spec:
  containers:
  - image: httpd
    imagePullPolicy: Always
    name: httpd
    ports:
    - containerPort: 80
      protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-lm7g7
      readOnly: true
  dnsPolicy: ClusterFirst
  nodeName: node01
  restartPolicy: Always
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  volumes:
  - name: default-token-lm7g7
    secret:
      defaultMode: 420
      secretName: default-token-lm7g7
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: 2018-11-27T07:13:09Z
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: 2018-11-27T07:13:23Z
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: 2018-11-27T07:13:09Z
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: docker://47663b8a6d882617b3caff81536220159ad7e9a2b5179f1dc5c05bfb7446520d
    image: httpd
    imageID: docker-pullable://docker.io/httpd@sha256:9753aabc6b0b8cd0a39733ec13b7aad59e51069ce96d63c6617746272752738e
    lastState: {}
    name: httpd
    ready: true
    restartCount: 0
    state:
      running:
        startedAt: 2018-11-27T07:13:23Z
  hostIP: 192.168.17.20
  phase: Running
  podIP: 172.17.40.2
  startTime: 2018-11-27T07:13:09Z

上記例では hostIP: 192.168.17.20 (node)上に pod (172.17.40.2)が作られていることがわかる。

node側でdocker ps コマンドを確認すると「httpd」イメージからコンテナが作成されて稼動していることが分かる。

[vagrant@k8s-node ~]$ sudo docker ps
CONTAINER ID        IMAGE                                      COMMAND              CREATED             STATUS              PORTS               NAMES
47663b8a6d88        httpd                                      "httpd-foreground"   2 weeks ago         Up 2 weeks                              k8s_httpd.1a4e2eba_httpd_default_e523b326-f213-11e8-b742-0800275ae9e7_a6b750a8
e63e9ebd8636        gcr.io/google_containers/pause-amd64:3.0   "/pause"             2 weeks ago         Up 2 weeks                              k8s_POD.b2390301_httpd_default_e523b326-f213-11e8-b742-0800275ae9e7_2ecf2e37
[vagrant@k8s-node ~]$


Podに特定のIPアドレスを割り当てる
kubernetesでは、どのPodがどのノードで実行されるかはPodの作成時に決定される。 つまり、Podが作成されるまではそれぞれのPodにどのIPアドレスが紐付けられるかは分からない。 そのため、指定したPodに特定のIPアドレスを割り当てるための「Service」という仕組みが用意されている。

以下のような service ファイルを定義する。

[vagrant@k8s-master ~]$ vim service-httpd.yaml

apiVersion: v1
kind: Service  <- Service定義
metadata:
  name: httpd-master
spec:
  ports:
    - port: 80
  selector:
    app: httpd ←対象とするPodをラベルで指定

Serviceを起動

[vagrant@k8s-master ~]$ kubectl create -f service-httpd.yaml
service "httpd-master" created

master側でkubectl get service を実行

[vagrant@k8s-master ~]$ kubectl get service
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
httpd-master   10.254.217.42   <none>        80/TCP    7m
kubernetes     10.254.0.1      <none>        443/TCP   23d

固定の CLUSTER IP (10.254.217.42)が設定されていることがわかる。
このIPアドレスへの接続は紐付けられたPodにルーティングされるようになっており、これを利用することでどのノード上でPodが動いているかを意識せずにサービスにアクセスできる。

node側で CLUSTER IP に接続してみる

[vagrant@k8s-node ~]$ curl 10.254.217.42
<html><body><h1>It works!</h1></body></html>


3. 参考にしたURL一覧

DockerとKubernetesが作る未来
https://www.slideshare.net/jacopen/dockerkubernetes

メモ:Google製DockerクラスタツールKubernetes
https://qiita.com/shouta-dev/items/ad876e6bd256d5d58ebb

VagrantでKubernetesクラスタを立てるhttps://qiita.com/awakia/items/fa054fd2a7c6329adac7

Kubernetesでクラスタ環境構築手順(1) - masterの作成
https://qiita.com/Esfahan/items/db7a79816731e6aa5cf5

Kubernetesでクラスタ環境構築手順(2) - nodeの作成
https://qiita.com/Esfahan/items/256fdb78e6a40b7c3e1f

Docker(コンテナ型仮想化)と Kubernetes についての簡単な紹介
https://ubiteku.oinker.me/2017/02/21/docker-and-kubernetes-intro/

Kubernetes を CentOS 7 で とりあえず始めてみるには
http://asuki-yt.hatenablog.jp/entry/2017/12/15/145501

kubernetesによるDockerコンテナ管理入門
https://knowledge.sakura.ad.jp/3681/







今回の"note"を気に入って頂けましたら、是非サポートをお願いいたします!