Kubernetesを1台のCentOS7で動かす

このエントリはKubernetesアドベントカレンダー2014の5日目です。

いよいよKubernetesを動かします。

今日のところはまずは1台で動かします。 VirtualBox上で起動したCentOS7にインストールして動かしてみます。 2CPU、メモリ512MBで動かしましたが動作確認だけなら特に問題ありませんでした。

Kubernetes v0.5.3の hack/local-〜.sh を使って起動します。 いろいろな起動方法がありますが、私にとってはこれが一番見通しがよかったのです。

CentOS7をインストール

まずは普通にインストールして起動します。 CentOS-7.0-1406-x86_64-Minimal をインストールしました。 kickstartファイルの一部を抜粋するとこんな感じです。

lang ja_JP.UTF-8
keyboard jp106
network --onboot yes --device eth0 --bootproto dhcp --noipv6
network --onboot yes --device eth1 --bootproto dhcp --noipv6
firewall --service=ssh
selinux --disabled
timezone --utc Asia/Tokyo

自分でこれをVagrantBoxに固めたものを使ったので、ネットワーク設定は以下のとおりになってました。 全てデフォルトです。

  • eth0(NAT): 10.0.2.0/24
  • eth1(Hostonly): disconnected

なおdockerとKubernetesのアドレス帯は以下のとおりです。

  • docker0: 172.17.0.0/16 ※コンテナ自体に割り当てられるIPアドレス
  • Kubernetes(portal_net): 10.0.0.0/24 ※KubetnetesのServiceのendpointになるIPアドレス

インストール

firewalloff にして、 golanggit をyumでインストールして、 etcd をインストールして、 etcdPATH に入れて、 dockerをインストールしてKubernetesをインストールします。あら簡単。

firewall-cmd --set-default-zone=trusted

yum -y clean all
yum -y update

yum -y install golang
yum -y install git

git clone https://github.com/coreos/etcd.git /opt/etcd
cd /opt/etcd
git checkout v0.4.6
./build
cp -a bin/etcd /usr/local/sbin/.

yum -y install docker
systemctl enable docker.service
systemctl start docker.service

git clone https://github.com/GoogleCloudPlatform/kubernetes.git /opt/kubernetes
cd /opt/kubernetes
git checkout v0.5.3

起動

以下のとおり起動します。あら簡単。

hack/local-up-cluster.sh のうち、 --portal_net のところは他のネットワークと重複しないようにしないとなりません。 今回私は変更しませんでしたが、必要なら変更してください。

cd /opt/kubernetes
export KUBERNETES_PROVIDER=local
export KUBERNETES_MASTER=http://localhost:8080
hack/local-up-cluster.sh

初回起動時はツールのビルドが入るので多少時間がかかります。

[root@localhost kubernetes]# hack/local-up-cluster.sh
+++ Building go targets for linux/amd64:
    cmd/kube-proxy
    cmd/kube-apiserver
    cmd/kube-controller-manager
    cmd/kubelet
    plugin/cmd/kube-scheduler
    cmd/kubecfg
    cmd/kubectl
    cmd/kubernetes
    cmd/e2e
    cmd/integration
+++ Placing binaries
Starting etcd
+++ etcd:
    {"action":"get","node":{"key":"/","dir":true}}
+++ apiserver:
    {"kind":"PodList","creationTimestamp":null,"selfLink":"/api/v1beta1/pods","resourceVersion":6,"apiVersion":"v1beta1","items":[]}
Local Kubernetes cluster is running. Press Ctrl-C to shut it down.
Logs:
  /tmp/kube-apiserver.log
  /tmp/kube-controller-manager.log
  /tmp/kubelet.log
  /tmp/kube-proxy.log
  /tmp/kube-scheduler.log

すると、こうなります

root      2528  0.0  0.2 113252  1180 pts/0    S+   01:58   0:00      |   \_ /bin/bash hack/local-up-cluster.sh
root      2806  0.2  1.2 331972  6032 pts/0    Sl+  01:59   0:00      |       \_ etcd -name test -data-dir /tmp/test-etcd.rpKb1u -addr 127.0.0.1:4001
root      2821  0.3  2.1 265832 10880 pts/0    Sl+  01:59   0:00      |       \_ /opt/kubernetes/_output/local/bin/linux/amd64/kube-apiserver -v=3 --address=127.0.0.1 --port=8080 --etcd_servers=http://127.0.0.1:4001 --portal_net=10.0.0.0/24 --cors_allowed_origins=/127.0.0.1(:[0-9]+)?$,/localhost(:[0-9]+)?$
root      2832  0.0  1.6 120964  8292 pts/0    Sl+  01:59   0:00      |       \_ /opt/kubernetes/_output/local/bin/linux/amd64/kube-controller-manager -v=3 --machines=127.0.0.1 --master=127.0.0.1:8080
root      2833  0.0  1.1 267628  5556 pts/0    Sl+  01:59   0:00      |       \_ /opt/kubernetes/_output/local/bin/linux/amd64/kubelet -v=3 --etcd_servers=http://127.0.0.1:4001 --hostname_override=127.0.0.1 --address=127.0.0.1 --port=10250
root      2834  0.1  1.0 200704  5400 pts/0    Sl+  01:59   0:00      |       \_ /opt/kubernetes/_output/local/bin/linux/amd64/kube-proxy -v=3 --master=http://127.0.0.1:8080
root      2835  0.0  1.0 118512  5296 pts/0    Sl+  01:59   0:00      |       \_ /opt/kubernetes/_output/local/bin/linux/amd64/kube-scheduler -v=3 --master=http://127.0.0.1:8080

動作確認

以下のようにして、 MinionPodServiceReplicationController の一覧が確認できます。

v0.5までは kubecfg を使う手順になってましたが、どうもv0.5からは kubectl を使うようです (でも今のところ kubecfg も使えます)。

cd /opt/kubernetes
export KUBERNETES_PROVIDER=local
export KUBERNETES_MASTER=http://localhost:8080

cluster/kubectl.sh get minions
cluster/kubectl.sh get pods
cluster/kubectl.sh get services
cluster/kubectl.sh get replicationControllers

Minion は自分しかいません。

[root@localhost kubernetes]# cluster/kubectl.sh get minions
NAME
127.0.0.1

Pod はまだ1つもありません。

[root@localhost kubernetes]# cluster/kubectl.sh get pods
NAME                IMAGE(S)            HOST                LABELS              STATUS

Service はapiserverがあります。 なおソートされないので実行するたびに表示順が変わります。

[root@localhost kubernetes]# cluster/kubectl.sh get services
NAME                LABELS              SELECTOR                                  IP                  PORT
kubernetes-ro                           component=apiserver,provider=kubernetes   10.0.0.45           80
kubernetes                              component=apiserver,provider=kubernetes   10.0.0.249          443

ReplicationController はまだ1つもありません。

[root@localhost kubernetes]# cluster/kubectl.sh get replicationControllers
NAME                IMAGE(S)            SELECTOR            REPLICAS

ちなみに kubectl-o json とすることでjsonで取得もできます(yamlもいけます)。

[root@localhost kubernetes]# cluster/kubectl.sh get services -o json
{
    "kind": "ServiceList",
    "creationTimestamp": null,
    "selfLink": "/api/v1beta1/services",
    "resourceVersion": 7,
    "apiVersion": "v1beta1",
    "items": [
        {
            "id": "kubernetes-ro",
            "uid": "a7da6401-7a2b-11e4-ab1a-08002716d207",
            "creationTimestamp": "2014-12-02T23:01:04+09:00",
            "selfLink": "/api/v1beta1/services/kubernetes-ro",
            "resourceVersion": 3,
            "namespace": "default",
            "port": 80,
            "protocol": "TCP",
            "selector": {
                "component": "apiserver",
                "provider": "kubernetes"
            },
            "containerPort": 0,
            "portalIP": "10.0.0.45"
        },
        {
            "id": "kubernetes",
            "uid": "a7da8a3d-7a2b-11e4-ab1a-08002716d207",
            "creationTimestamp": "2014-12-02T23:01:04+09:00",
            "selfLink": "/api/v1beta1/services/kubernetes",
            "resourceVersion": 4,
            "namespace": "default",
            "port": 443,
            "protocol": "TCP",
            "selector": {
                "component": "apiserver",
                "provider": "kubernetes"
            },
            "containerPort": 0,
            "portalIP": "10.0.0.249"
        }
    ]
}

なおjsonでも items への登場順はソートされません。

使ってみる

リポジトリ内に用意されている guestbook example を動かしてみます。

これはfrontend(php) x3、redis-master x1、redis-slave x2 という構成のサイトを想定しています。

段取りは以下のとおりです。

  1. redis-masterの Pod を作成
  2. redis-masterの Service を作成
  3. redis-spaveの ReplicationController を作成(このとき Pod もできる)
  4. redis-slaveの Service を作成
  5. frontendの ReplicationController を作成(このとき Pod もできる)

redis-master

  • redis-masterの Pod を作成
  • redis-masterの Service を作成
cd /opt/kubernetes
export KUBERNETES_PROVIDER=local
export KUBERNETES_MASTER=http://localhost:8080

cluster/kubectl.sh create -f examples/guestbook/redis-master.json pods
cluster/kubectl.sh create -f examples/guestbook/redis-master-service.json services

create 〜 pods した時に、 Pod に必要なdocker imageを docker pull するため、かなーり待ちます。 このときに kubectl.sh get pods でSTATUSを見ると Pending で、準備完了し起動したら Running になります。

docker images -a しながらヤキモキしましょう。 たまに docker pull できなくて止まっている時があるので、あまりにもな場合はdockerのログを見て進んでいるか確認してみてください。

[root@localhost kubernetes]# cluster/kubectl.sh get pods
NAME                IMAGE(S)            HOST                LABELS              STATUS
redis-master        dockerfile/redis    127.0.0.1/          name=redis-master   Pending
[root@localhost kubernetes]# cluster/kubectl.sh get services
[root@localhost kubernetes]# cluster/kubectl.sh get services
NAME                LABELS              SELECTOR                                  IP                  PORT
kubernetes-ro                           component=apiserver,provider=kubernetes   10.0.0.45           80
kubernetes                              component=apiserver,provider=kubernetes   10.0.0.249          443
redis-master        name=redis-master   name=redis-master                         10.0.0.98           6379

redis-slave

  • redis-spaveの ReplicationController を作成(このとき Pod もできる)
  • redis-slaveの Service を作成
cluster/kubectl.sh create -f examples/guestbook/redis-slave-controller.json create replicationControllers
cluster/kubectl.sh create -f examples/guestbook/redis-slave-service.json create services

こちらは create 〜 replicationControllers したときに docker pull します。

このとき Pod の状態を見ると2つのredis-slaveのうち1つは unassigned になってます。 これはredis-slaveの Pod が多重度2になっているものの、 1台しかなくて配置先がないので困っている状態です。 いまは気にせず進みましょう。 配置先が足りなくても動くようにうまくやってくれるのがKubernetesですから気にしない。

[root@localhost kubernetes]# cluster/kubectl.sh get pods
NAME                                   IMAGE(S)                   HOST                LABELS                              STATUS
redis-master                           dockerfile/redis           127.0.0.1/          name=redis-master                   Running
0260d085-7a2c-11e4-ab1a-08002716d207   brendanburns/redis-slave   127.0.0.1/          name=redisslave,uses=redis-master   Running
02669c42-7a2c-11e4-ab1a-08002716d207   brendanburns/redis-slave           name=redisslave,uses=redis-master   Pending

frontend

  • frontendの ReplicationController を作成(このとき Pod もできる)
cluster/kubectl.sh create -f examples/guestbook/frontend-controller.json create replicationControllers

unassigned 以外の Pod が全てRunningになれば起動完了です。

[root@localhost kubernetes]# cluster/kubectl.sh get pods
NAME                                   IMAGE(S)                   HOST                LABELS                                       STATUS
1afd8284-7a2c-11e4-ab1a-08002716d207   brendanburns/php-redis     127.0.0.1/          name=frontend,uses=redisslave,redis-master   Running
1afef414-7a2c-11e4-ab1a-08002716d207   brendanburns/php-redis             name=frontend,uses=redisslave,redis-master   Pending
1affa738-7a2c-11e4-ab1a-08002716d207   brendanburns/php-redis             name=frontend,uses=redisslave,redis-master   Pending
redis-master                           dockerfile/redis           127.0.0.1/          name=redis-master                            Running
0260d085-7a2c-11e4-ab1a-08002716d207   brendanburns/redis-slave   127.0.0.1/          name=redisslave,uses=redis-master            Running
02669c42-7a2c-11e4-ab1a-08002716d207   brendanburns/redis-slave           name=redisslave,uses=redis-master            Pending

ここまでできたら http://ホストのIPアドレス:8000 にアクセスするとguestbookの画面が見られます。 このときの 8000examples/guestbook/frontend-controller.json で指定されています。

kubernetes/frontend-controller.json at v0.5.3 · GoogleCloudPlatform/kubernetes

screenshot

あとは、GCPのHTTP LoadBalancerやELBみたいなのにこの ホストIP:8000 をぶらさげればサービスインです。

そういうのがない場合に、別の Pod からシステム内APIみたいな感じでアクセスしたい要件とかがある場合は、frontendの Service を作成をするとそのへんをうまく解決できるようになります。

cluster/kubectl.sh create -f examples/guestbook/frontend-service.json create services

確認

起動完了したあとのdockerのプロセスツリーはこんな感じになってます。 redis-master, redisslave, foregroundそれぞれに docker-proxy/pause が起動しています。

root      2351 10.3  7.0 1272496 35340 ?       Ssl  22:23   4:22 /usr/bin/docker -d --selinux-enabled
root      3851  0.0  1.0 207360  5456 ?        Sl   23:02   0:00  \_ docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 6379 -container-ip 172.17.0.2 -container-port 6379
root      3854  0.0  0.0 265332   220 ?        Ssl  23:02   0:00  \_ /pause
root      3917  0.3  0.4  35172  2336 ?        Ssl  23:02   0:00  \_ redis-server *:6379
root      4054  0.0  1.0 207360  5492 ?        Sl   23:03   0:00  \_ docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 6380 -container-ip 172.17.0.3 -container-port 6379
root      4056  0.0  0.0 265268   216 ?        Ssl  23:03   0:00  \_ /pause
root      4102  0.0  0.1   4444   564 ?        Ss   23:03   0:00  \_ /bin/sh -c /run.sh
root      4108  0.0  0.2  17968  1452 ?        S    23:03   0:00  |   \_ /bin/bash /run.sh
root      4109  0.2  0.4  35172  2272 ?        Sl   23:03   0:00  |       \_ redis-server *:6379
root      4232  0.0  1.0 207360  5488 ?        Sl   23:04   0:00  \_ docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8000 -container-ip 172.17.0.4 -container-port 80
root      4237  0.0  0.0 265268   232 ?        Ssl  23:04   0:00  \_ /pause
root      4304  0.0  0.1   4404   584 ?        Ss   23:04   0:00  \_ /bin/sh -c /run.sh
root      4310  0.4  2.5  53148 12916 ?        S    23:04   0:00      \_ /usr/bin/python /usr/bin/supervisord -n
root      4329  0.2  3.1 259964 15980 ?        S    23:04   0:00          \_ apache2 -D FOREGROUND
33        4336  0.0  1.3 260036  6648 ?        S    23:04   0:00              \_ apache2 -D FOREGROUND
33        4337  0.0  1.1 259988  5936 ?        S    23:04   0:00              \_ apache2 -D FOREGROUND
33        4338  0.0  1.1 259988  5936 ?        S    23:04   0:00              \_ apache2 -D FOREGROUND
33        4339  0.0  1.1 259988  5936 ?        S    23:04   0:00              \_ apache2 -D FOREGROUND
33        4340  0.0  1.1 259988  5936 ?        S    23:04   0:00              \_ apache2 -D FOREGROUND

docker ps はこんな感じです。

[root@localhost kubernetes]# docker ps
CONTAINER ID        IMAGE                             COMMAND                CREATED              STATUS              PORTS                    NAMES
ebace1b18bcb        brendanburns/php-redis:latest     "/bin/sh -c /run.sh"   About a minute ago   Up About a minute                            k8s_php-redis.e604bf52_1afd8284-7a2c-11e4-ab1a-08002716d207.default.etcd_1afe8eef-7a2c-11e4-ab1a-08002716d207_e1c34d2a
66a48c43e9f1        kubernetes/pause:latest           "/pause"               About a minute ago   Up About a minute   0.0.0.0:8000->80/tcp     k8s_net.163f8d3c_1afd8284-7a2c-11e4-ab1a-08002716d207.default.etcd_1afe8eef-7a2c-11e4-ab1a-08002716d207_e78b1013
8dfc12a5dc4b        brendanburns/redis-slave:latest   "/bin/sh -c /run.sh"   About a minute ago   Up About a minute                            k8s_slave.5e8b35d1_0260d085-7a2c-11e4-ab1a-08002716d207.default.etcd_0261285b-7a2c-11e4-ab1a-08002716d207_d72a8f5d
0538052a80f2        kubernetes/pause:latest           "/pause"               About a minute ago   Up About a minute   0.0.0.0:6380->6379/tcp   k8s_net.feb08db6_0260d085-7a2c-11e4-ab1a-08002716d207.default.etcd_0261285b-7a2c-11e4-ab1a-08002716d207_3701b890
770d7fb4a7a2        dockerfile/redis:latest           "redis-server /etc/r   2 minutes ago        Up 2 minutes                                 k8s_master.257ca611_redis-master.default.etcd_eab4a897-7a2b-11e4-ab1a-08002716d207_b3e34d02
9be75144fb68        kubernetes/pause:latest           "/pause"               2 minutes ago        Up 2 minutes        0.0.0.0:6379->6379/tcp   k8s_net.7168dbe_redis-master.default.etcd_eab4a897-7a2b-11e4-ab1a-08002716d207_ef4cfaa0

docker inspectiptables -t nat -nv -L などして、動作状態を詳しく見てみてください。

おまけ

書きながらふとリポジトリを見たら v0.6でstandalone modeが入るっぽい雰囲気 なコミットあって、このエントリもちょっとアレになるかもしれません。南無。


See also