理解Kubernetes系列文章:
准备 3个Ubuntu节点,操作系统版本为 16.04,并做好以下配置:
节点名称 | IP地址 | etcd | flanneld | K8S | docker |
kub-node-0 | 172.23.100.4 | Y | Y |
master:
kubctl
kube-apiserver
kuber-controller
kuber-scheduler
|
Y |
kub-node-1 | 172.23.100.5 | Y | Y | node: kube-proxy kubelet |
Y |
kub-node-2 | 172.23.100.6 | Y | Y | node: kube-proxy kubelet |
Y |
ETCD_VERSION=${ETCD_VERSION:-"3.2.5"} ETCD="etcd-v${ETCD_VERSION}-linux-amd64" curl -L https://github.com/coreos/etcd/releases/download/v${ETCD_VERSION}/${ETCD}.tar.gz -o etcd.tar.gz tar xzf etcd.tar.gz -C /tmp mv /tmp/etcd-v${ETCD_VERSION}-linux-amd64 /opt/bin/
sudo mkdir -p /var/lib/etcd/ sudo mkdir -p /opt/config/
ETCD_DATA_DIR=/var/lib/etcd ETCD_NAME="kub-node-0" ETCD_INITIAL_CLUSTER="kub-node-0=http://172.23.100.4:2380,kub-node-1=http://172.23.100.5:2380,kub-node-2=http://172.23.100.6:2380" ETCD_INITIAL_CLUSTER_STATE=new ETCD_LISTEN_PEER_URLS=http://172.23.100.4:2380 ETCD_INITIAL_ADVERTISE_PEER_URLS=http://172.23.100.4:2380 ETCD_ADVERTISE_CLIENT_URLS=http://172.23.100.4:2379 ETCD_LISTEN_CLIENT_URLS=http://172.23.100.4:2379,http://127.0.0.1:2379
注意:
[Unit] Description=Etcd Server Documentation=https://github.com/coreos/etcd After=network.target [Service] User=root Type=simple EnvironmentFile=-/opt/config/etcd.conf ExecStart=/opt/bin/etcd Restart=on-failure RestartSec=10s LimitNOFILE=40000 [Install] WantedBy=multi-user.target
每个节点上都是一样的。
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
root@kub-node-2:/home/ubuntu# /opt/bin/etcdctl cluster-health member 664b85ff39242fbc is healthy: got healthy result from http://172.23.100.6:2379 member 9dd263662a4b6f73 is healthy: got healthy result from http://172.23.100.4:2379 member b17535572fd6a37b is healthy: got healthy result from http://172.23.100.5:2379 cluster is healthy
root@kub-node-0:/home/ubuntu# /opt/bin/etcdctl member list 9dd263662a4b6f73: name=kub-node-0 peerURLs=http://172.23.100.4:2380 clientURLs=http://172.23.100.4:2379 isLeader=false b17535572fd6a37b: name=kub-node-1 peerURLs=http://172.23.100.5:2380 clientURLs=http://172.23.100.5:2379 isLeader=true e6db3cac1db23670: name=kub-node-2 peerURLs=http://172.23.100.6:2380 clientURLs=http://172.23.100.6:2379 isLeader=false
在每个节点上:
curl -L https://github.com/coreos/flannel/releases/download/v0.8.0/flannel-v0.8.0-linux-amd64.tar.gz flannel.tar.gz tar xzf flannel.tar.gz -C /tmp mv /tmp/flanneld /opt/bin/
[Unit] Description=Flanneld Documentation=https://github.com/coreos/flannel After=network.target Before=docker.service [Service] User=root ExecStart=/opt/bin/flanneld \ --etcd-endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" \ --iface=172.23.100.4 \ --ip-masq Restart=on-failure Type=notify LimitNOFILE=65536
注意:在每个节点上,iface 设置为本机ip。
/opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" mk /coreos.com/network/config \ '{"Network":"10.1.0.0/16", "Backend": {"Type": "vxlan"}}'
确认:
root@kub-node-0:/home/ubuntu# /opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379" get /coreos.com/network/config {"Network":"10.1.0.0/16", "Backend": {"Type": "vxlan"}}
systemctl daemon-reload
systemctl enable flanneld
systemctl start flanneld
备注:flannel服务需要先于Docker启动。flannel服务启动时主要做了以下几步的工作:
此时,能看到 etcd 中的 subnet:
root@kub-node-0:/home/ubuntu/kub# /opt/bin/etcdctl --endpoints="http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.4:2379"; ls /coreos.com/network/subnets /coreos.com/network/subnets/10.1.35.0-24 /coreos.com/network/subnets/10.1.1.0-24 /coreos.com/network/subnets/10.1.79.0-24
root@kub-node-0:/home/ubuntu/kub# ifconfig flannel.1 flannel.1 Link encap:Ethernet HWaddr 22:fc:69:01:33:30 inet addr:10.1.35.0 Bcast:0.0.0.0 Mask:255.255.255.255 root@kub-node-1:/home/ubuntu# ifconfig flannel.1 flannel.1 Link encap:Ethernet HWaddr 0a:6e:a6:6f:95:04 inet addr:10.1.1.0 Bcast:0.0.0.0 Mask:255.255.255.255 root@kub-node-2:/home/ubuntu# ifconfig flannel.1 flannel.1 Link encap:Ethernet HWaddr 6e:10:b3:53:1e:f4 inet addr:10.1.79.0 Bcast:0.0.0.0 Mask:255.255.255.255
sudo apt-get update sudo apt-get install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install docker-ce
创建并运行 hello-world 容器:
root@kub-node-0:/home/ubuntu/kub# docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world ca4f61b1923c: Pull complete Digest: sha256:445b2fe9afea8b4aa0b2f27fe49dd6ad130dfe7a8fd0832be5de99625dad47cd Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly.
root@kub-node-0:/home/ubuntu/kub# mk-docker-opts.sh -i root@kub-node-0:/home/ubuntu/kub# source /run/flannel/subnet.env root@kub-node-0:/home/ubuntu/kub# ifconfig docker0 docker0 Link encap:Ethernet HWaddr 02:42:bc:71:d0:22 inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0 inet6 addr: fe80::42:bcff:fe71:d022/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:258 (258.0 B) root@kub-node-0:/home/ubuntu/kub# ifconfig docker0 ${FLANNEL_SUBNET} root@kub-node-0:/home/ubuntu/kub# ifconfig docker0 docker0 Link encap:Ethernet HWaddr 02:42:bc:71:d0:22 inet addr:10.1.35.1 Bcast:10.1.35.255 Mask:255.255.255.0 inet6 addr: fe80::42:bcff:fe71:d022/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:258 (258.0 B)
[Service] Type=notify # the default is not to use systemd for cgroups because the delegate issues still # exists and systemd currently does not support the cgroup feature set required # for containers run by docker EnvironmentFile=/var/run/flannel/subnet.env ExecStart=/usr/bin/dockerd -g /data/docker --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} ExecReload=/bin/kill -s HUP $MAINPID #ExecStart=/usr/bin/dockerd -H fd:// #ExecReload=/bin/kill -s HUP $MAINPID
iptables -F iptables -X iptables -Z iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables-save
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
在 0 节点上做如下操作。
curl -L https://dl.k8s.io/v1.8.5/kubernetes-server-linux-amd64.tar.gz kuber.tar.gz tar xzf kuber.tar.gz -C /tmp3 mv /tmp3/kubernetes/server/bin/* /opt/bin
[Unit] Description=Kubernetes API Server Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] User=root ExecStart=/opt/bin/kube-apiserver \ --secure-port=6443 \ --etcd-servers=http://172.23.100.4:2379,http://172.23.100.5:2379,http://172.23.100.6:2379 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --allow-privileged=false \ --service-cluster-ip-range=192.1.0.0/16 \ --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,SecurityContextDeny,ResourceQuota \ --service-node-port-range=30000-32767 \ --advertise-address=172.23.100.4 \ --client-ca-file=/root/key/ca.crt \ --tls-cert-file=/root/key/server.crt \ --tls-private-key-file=/root/key/server.key Restart=on-failure Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target
[Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/kubernetes/kubernetes [Service] User=root ExecStart=/opt/bin/kube-controller-manager \ --master=https://172.23.100.4:6443 \ --root-ca-file=/root/key/ca.crt \ --service-account-private-key-file=/root/key/server.key \ --kubeconfig=/etc/kubernetes/kubeconfig \ --logtostderr=false \ --log-dir=/var/log/kubernetes Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
[Unit] Description=Kubernetes Scheduler Documentation=https://github.com/kubernetes/kubernetes [Service] User=root ExecStart=/opt/bin/kube-scheduler \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --master=https://172.23.100.4:6443 \ --kubeconfig=/etc/kubernetes/kubeconfig Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl enable kube-apiserver systemctl enable kube-controller-manager systemctl enable kube-scheduler systemctl enable flanneld systemctl start kube-apiserver systemctl start kube-controller-manager systemctl start kube-scheduler
systemctl status kube-apiserver systemctl status kube-controller-manager systemctl status kube-scheduler
[req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = kubernetes DNS.2 = kubernetes.default DNS.3 = kubernetes.default.svc DNS.4 = kubernetes.default.svc.cluster.local DNS.5 = master IP.1 = 192.1.0.1 IP.2 = 172.23.100.4
openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=company.com" -days 10000 -out ca.crt openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=master" -config master_ssl.cnf -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 10000 -extensions v3_req -extfile master_ssl.cnf -out server.crt openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/CN=node" -out client.csr openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 10000
root@kub-node-0:/home/ubuntu/kub# ls /root/key ca.crt ca.key client.crt client.key server.crt server.key
在 1 和 2 上分别执行下面的操作。下面的示例以节点2为例,1上需要修改IP地址。
CLINET_IP=172.23.100.6 openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/CN=${CLINET_IP}" -out client.csr openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 10000
root@kub-node-2:/home/ubuntu/kub# ls -lt total 8908 -rw-r--r-- 1 root root 985 Dec 31 20:57 client.crt -rw-r--r-- 1 root root 17 Dec 31 20:57 ca.srl -rw-r--r-- 1 root root 895 Dec 31 20:57 client.csr -rw-r--r-- 1 root root 1675 Dec 31 20:57 client.key -rw-r--r-- 1 root root 1099 Dec 31 20:54 ca.crt -rw-r--r-- 1 root root 1675 Dec 31 20:54 ca.key
root@kub-node-2:/home/ubuntu# ls /root/key ca.crt ca.key client.crt client.key
apiVersion: v1 clusters: - cluster: certificate-authority: /root/key/ca.crt server: https://172.23.100.4:6443 name: ubuntu contexts: - context: cluster: ubuntu user: ubuntu name: ubuntu current-context: ubuntu kind: Config preferences: {} users: - name: ubuntu user: client-certificate: /root/key/client.crt client-key: /root/key/client.key
在 0 节点上,创建 /root/.kube/config 文件:
apiVersion: v1
clusters:
- cluster:
certificate-authority: /root/key/ca.crt
name: ubuntu
contexts:
- context:
cluster: ubuntu
user: ubuntu
name: ubuntu
current-context: ubuntu
kind: Config
preferences: {}
users:
- name: ubuntu user: client-certificate: /root/key/client.crt client-key: /root/key/client.key
节点1 和 2 为 K8S node 节点。在它们上执行下面的操作。
同 2.4.1 。
[Unit] Description=Kubernetes Kubelet After=docker.service Requires=docker.service [Service] ExecStart=/opt/bin/kubelet \ --hostname-override=172.23.100.5 \ --pod-infra-container-image="docker.io/kubernetes/pause" \ --cluster-domain=cluster.local \ --log-dir=/var/log/kubernetes \ --cluster-dns=192.1.0.100 \ --kubeconfig=/etc/kubernetes/kubeconfig \ --logtostderr=false Restart=on-failure KillMode=process [Install] WantedBy=multi-user.target [Unit] Description=Kubernetes Proxy After=network.target
[Unit] Description=Kubernetes Proxy After=network.target [Service] ExecStart=/opt/bin/kube-proxy \ --hostname-override=172.23.100.5 \ --master=https://172.23.100.4:6443 \ --log-dir=/var/log/kubernetes \ --kubeconfig=/etc/kubernetes/kubeconfig \ --logtostderr=false Restart=on-failure [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl enable kubelet systemctl enable kube-proxy systemctl start kubelet systemctl start kube-proxy
systemctl status kubelet
systemctl status kube-proxy
在节点 0 上运行以下命令。
root@kub-node-0:/home/ubuntu/kub# kubectl cluster-info Kubernetes master is running at http://localhost:8080
root@kub-node-0:/home/ubuntu/kub# kubectl get nodes NAME STATUS ROLES AGE VERSION 172.23.100.5 Ready2d v1.8.5 172.23.100.6 Ready 2d v1.8.5
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: my-nginx4 spec: replicas: 2 template: metadata: labels: app: my-nginx4 spec: containers: - name: my-nginx4 image: nginx ports: - containerPort: 80
root@kub-node-0:/home/ubuntu/kub# kubectl create -f nginx4.yml deployment "my-nginx4" created
root@kub-node-0:/home/ubuntu/kub# kubectl get all NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/my-nginx4 2 2 2 2 3m NAME DESIRED CURRENT READY AGE rs/my-nginx4-75bbfccc7c 2 2 2 3m NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/my-nginx4 2 2 2 2 3m NAME DESIRED CURRENT READY AGE rs/my-nginx4-75bbfccc7c 2 2 2 3m NAME READY STATUS RESTARTS AGE po/my-nginx4-75bbfccc7c-5frpl 1/1 Running 0 3m po/my-nginx4-75bbfccc7c-5kr4j 1/1 Running 0 3m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/kubernetes ClusterIP 192.1.0.1443/TCP 2d
root@kub-node-0:/home/ubuntu/kub# kubectl describe deployments my-nginx4 Name: my-nginx4 Namespace: default CreationTimestamp: Wed, 03 Jan 2018 09:16:44 +0800 Labels: app=my-nginx4 Annotations: deployment.kubernetes.io/revision=1 Selector: app=my-nginx4 Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge Pod Template: Labels: app=my-nginx4 Containers: my-nginx4: Image: nginx Port: 80/TCP Environment:Mounts: Volumes: Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable OldReplicaSets: NewReplicaSet: my-nginx4-75bbfccc7c (2/2 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 1m deployment-controller Scaled up replica set my-nginx4-75bbfccc7c to 2
root@kub-node-0:/home/ubuntu/kub# kubectl describe pod my-nginx4-75bbfccc7c-5frpl Name: my-nginx4-75bbfccc7c-5frpl Namespace: default Node: 172.23.100.5/172.23.100.5 Start Time: Wed, 03 Jan 2018 09:16:45 +0800 Labels: app=my-nginx4 pod-template-hash=3166977737 Annotations: kubernetes.io/created-by={"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"default","name":"my-nginx4-75bbfccc7c","uid":"c2d83729-f023-11e7-a605-fa163e9a22a... Status: Running IP: 10.1.1.3 Created By: ReplicaSet/my-nginx4-75bbfccc7c Controlled By: ReplicaSet/my-nginx4-75bbfccc7c Containers: my-nginx4: Container ID: docker://4a994121e309fb81181e22589982bf8c053287616ba7c92dcddc5e7fb49927b1 Image: nginx Image ID: docker-pullable://nginx@sha256:cf8d5726fc897486a4f628d3b93483e3f391a76ea4897de0500ef1f9abcd69a1 Port: 80/TCP State: Running Started: Wed, 03 Jan 2018 09:16:53 +0800 Ready: True Restart Count: 0 Environment:Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-b2p4z (ro) Conditions: Type Status Initialized True Ready True PodScheduled True Volumes: default-token-b2p4z: Type: Secret (a volume populated by a Secret) SecretName: default-token-b2p4z Optional: false QoS Class: BestEffort Node-Selectors: Tolerations: Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 5m default-scheduler Successfully assigned my-nginx4-75bbfccc7c-5frpl to 172.23.100.5 Normal SuccessfulMountVolume 5m kubelet, 172.23.100.5 MountVolume.SetUp succeeded for volume "default-token-b2p4z" Normal Pulling 5m kubelet, 172.23.100.5 pulling image "nginx" Normal Pulled 5m kubelet, 172.23.100.5 Successfully pulled image "nginx" Normal Created 5m kubelet, 172.23.100.5 Created container Normal Started 5m kubelet, 172.23.100.5 Started container
root@kub-node-1:/home/ubuntu# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4a994121e309 nginx "nginx -g 'daemon of…" 2 minutes ago Up 2 minutes k8s_my-nginx4_my-nginx4-75bbfccc7c-5frpl_default_c35b9521-f023-11e7-a605-fa163e9a22a6_0 e3f39d708800 kubernetes/pause "/pause" 2 minutes ago Up 2 minutes k8s_POD_my-nginx4-75bbfccc7c-5frpl_default_c35b9521-f023-11e7-a605-fa163e9a22a6_0
root@kub-node-0:/home/ubuntu/kub# kubectl expose deployment my-nginx4 --type=NodePort --name=nginx-nodeport service "nginx-nodeport" exposed
root@kub-node-0:/home/ubuntu/kub# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 192.1.0.1443/TCP 2d nginx-nodeport NodePort 192.1.216.223 80:31362/TCP 31s
root@kub-node-0:/home/ubuntu/kub# curl http://172.23.100.5:31362Welcome to nginx! Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to "http://nginx.org/">nginx.org.
Commercial support is available at "http://nginx.com/">nginx.com.Thank you for using nginx.
W0101 20:25:25.636397 25702 helpers.go:771] eviction manager: no observation found for eviction signal allocatableNodeFs.available W0101 20:25:35.680877 25702 helpers.go:771] eviction manager: no observation found for eviction signal allocatableNodeFs.available W0101 20:25:45.728875 25702 helpers.go:771] eviction manager: no observation found for eviction signal allocatableNodeFs.available W0101 20:25:55.756455 25702 helpers.go:771] eviction manager: no observation found for eviction signal allocatableNodeFs.available
root@kub-node-0:/home/ubuntu# kubectl get pods NAME READY STATUS RESTARTS AGE hello-world-5c9bd8867-76jjg 0/1 CrashLoopBackOff 7 12m hello-world-5c9bd8867-92275 0/1 CrashLoopBackOff 7 12m hello-world-5c9bd8867-cn75n 0/1 CrashLoopBackOff 7 12m
E0101 22:34:51.908652 29137 kuberuntime_manager.go:633] createPodSandbox for pod "my-nginx3-596b5c5f58-vgvlb_default(aedfbe1b-eefc-11e7-b10d-fa163e9a22a6)" failed: rpc error: code = Unknown desc = failed pulling image "gcr.io/google_containers/pause-amd64:3.0": Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) E0101 22:34:51.908755 29137 pod_workers.go:182] Error syncing pod aedfbe1b-eefc-11e7-b10d-fa163e9a22a6 ("my-nginx3-596b5c5f58-vgvlb_default(aedfbe1b-eefc-11e7-b10d-fa163e9a22a6)"), skipping: failed to "CreatePodSandbox" for "my-nginx3-596b5c5f58-vgvlb_default(aedfbe1b-eefc-11e7-b10d-fa163e9a22a6)" with CreatePodSandboxError: "CreatePodSandbox for pod \"my-nginx3-596b5c5f58-vgvlb_default(aedfbe1b-eefc-11e7-b10d-fa163e9a22a6)\" failed: rpc error: code = Unknown desc = failed pulling image \"gcr.io/google_containers/pause-amd64:3.0\": Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)”
LoadBalancer 类型的 service 后,该 service 的 EXTERNAL-IP 一直停留在 Pending。其原因是因为该功能需要云平台上支持。改为 NodePort 就正常了。