基础环境
CentOS 7.3 64bit
Docker 1.13.0
Kubernetes 1.5.4
etcd 3.1.0
系统基础配置
10.201.3.222 Master
10.201.3.223 Node、etcd(leader)
10.201.3.224 Node、etcd(follower)
设置hostname 1 hostnamectl --static set -hostname <hostname>
关闭防火墙 & selinux 1 2 3 4 systemctl disable firewalld systemctl stop firewalld sed -i '/SELINUX/s/\(enforcing\|permissive\)/disabled/' /etc/selinux/config setenforce 0
YUM源设置
安装Docker & kubernetes组件 1 yum install -y ebtables socat docker-engine-1.13 .0 docker-engine-selinux-1.13 .0 kubelet kubeadm kubectl kubernetes-cni
部署etcd集群 Kubernetes使用etcd做存储,默认会部署单点的etcd,为了高可用单独部署etcd集群。
10.201.3.223:leader
10.201.3.224:follower
2379
端口:etcd提供给外部客户端端口(etcd2.0前为4001
)
2380
端口:etcd集群节点通信端口(etcd2.0前为7001
)
安装etcd
配置etcd /etc/etcd/etcd.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ETCD_NAME=etcd0 ETCD_DATA_DIR="/var/lib/etcd/etcd0" ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.201.3.223:2380" ETCD_INITIAL_CLUSTER="etcd0=http://10.201.3.223:2380,etcd1=http://10.201.3.224:2380" ETCD_INITIAL_CLUSTER_STATE="new" ETCD_INITIAL_CLUSTER_TOKEN="test-etcd-cluster" ETCD_ADVERTISE_CLIENT_URLS="http://10.201.3.223:2379,http://10.201.3.223:4001"
启动etcd集群 1 2 3 systemctl enable etcd systemctl start etcd systemctl status etcd
查看etcd集群状态 1 2 3 4 5 6 7 8 9 10 etcdctl cluster-health etcdctl member list
etcd集群增加新节点
启动Docker & Kubelet 在所有节点启动Docker、Kubelet,Kubelet因为没有配置可能无法启动,但没关系。
1 2 systemctl enable docker && systemctl start docker systemctl enable kubelet && systemctl start kubelet
导出导入镜像 由于Kubernetes组件都容器化了,需要到gcr.io
上pull镜像,但由于GFW的原因无法pull。要么在国外机器pull镜像后导入然后在导入到本地集群,要么使用代理,这里使用前者方法。再或者绑定hosts也可,pull镜像比较慢61.91.161.217 gcr.io www.gcr.io
Kubernetes1.5.4所需要的镜像
gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
gcr.io/google_containers/exechealthz-amd64:1.2
gcr.io/google_containers/kube-apiserver-amd64:v1.5.4
gcr.io/google_containers/kube-controller-manager-amd64:v1.5.4
gcr.io/google_containers/kube-discovery-amd64:1.0
gcr.io/google_containers/kubedns-amd64:1.9
gcr.io/google_containers/kube-dnsmasq-amd64:1.4
gcr.io/google_containers/kube-proxy-amd64:v1.5.4
gcr.io/google_containers/kube-scheduler-amd64:v1.5.4
gcr.io/google_containers/pause-amd64:3.0
gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0
gcr.io/google_containers/etcd-amd64:3.0.14-kubeadm
导出镜像 所有节点都需要导入镜像
1 docker save `docker images | grep -v TAG | awk '{print $1":"$2}' ` > kube.tar
导入镜像 将导出的镜像下载到本地集群然后导入
部署k8s集群 初始化集群 在master节点使用kubeadm
初始化集群,初始化过程中若发现本地没有镜像会去gcr.io
pull镜像。 使用kubeadm init
初始化集群时若是使用Flannel 网络的话需要添加--pod-network-cidr=10.244.0.0/16
,性能上Flannel会比Weave好,生产环境的话可以考虑Open vSwitch。
1 2 3 4 5 6 export KUBE_COMPONENT_LOGLEVEL='--v=1' kubeadm init --use-kubernetes-version v1.5.4 --api-advertise-addresses=10.201 .3.222 --external-etcd-endpoints http://10.201 .3.223 :2379 ,http://10.201 .3.224 :2379 kubeadm init --use-kubernetes-version v1.5.4 --api-advertise-addresses=10.201 .3.222 --pod-network-cidr=10.244 .0.0 /16 --external-etcd-endpoints http://10.201 .3.223 :2379 ,http://10.201 .3.224 :2379
执行完kubeadm init 初始化集群后会生成一个token ,需要记录便于以后添加Node进集群使用。 假若丢失了token 可使用命令查看
1 kubectl -n kube-system get secret clusterinfo -o yaml | grep token-map | awk '{print $2}' | base64 --decode | sed "s|{||g;s|}||g;s|:|.|g;s/\"//g;" | xargs echo
记录Node加入集群命令 kubeadm init
初始化完后会给出其余Node节点加入集群的命令,记录下来方便其余Node加入集群
1 kubeadm join --token=06 ac4c.a0f93b8da729ac48 10.201 .3.222
查看k8s节点集群状态
设置master运行Pod 默认master节点不会运行Pod,可通过命令设置运行在master节点运行Pod
1 kubectl taint nodes --all dedicated-
添加Node节点 Kubernetes的master节点部署成功后,可将其余Node节点加入集群 之前步骤已将Docker、Kubelet启动并且将所需的镜像都导入,所以直接将节点添加入集群即可。在Node节点上执行(10.201.3.222
为master节点):
1 kubeadm join --token=06 ac4c.a0f93b8da729ac48 10.201 .3.222
部署Pod网络 为了使不同Node之间的Pod能相互通信,需要专门部署Pod网络。一般默认可使用Weave,性能上有要求可使用Flannel,生产环境可考虑Open vSwitch。 若是部署Flannel网络,kube-flannel.yml
文件中的net-conf.json
/Network
网段要和--pod-network-cidr=10.244.0.0/16
设置保持一致 。
1 2 3 4 kubectl apply -f https://git.io/weave-kube kubectl create -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
DNS注意事项 Kubernetes的DNS功能是有kube-dns
提供的,kube-dns依赖Pod网络,所以在Pod网络弄好前kube-dns都会是ContainerCreating
状态。通过以下命令查看所有Pod服务,若都正常则状态都是Running
。
1 kubectl get pods --all-namespaces
扩展kube-dns数量 DNS服务为重要服务,使用kubeadm
创建的kube-dns
是单点的,一旦该Pod出现问题整个集群的DNS服务就瘫痪了,所有要扩展kube-dns
数量以防单点故障。
1 2 3 4 kubectl --namespace=kube-system scale deployment kube-dns --replicas=<NUMBER> kubectl get pods --namespace=kube-system | grep 'kube-dns'
部署Dashboard Kubernetes提供Web的Dashboard图形界面管理集群 镜像同样需要pull后导出再导入到本地,这里kubernetes-dashboard.yaml
中的镜像为gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.0
1 2 3 4 5 6 wget https://rawgit.com/kubernetes/dashboard/master/src/deploy/kubernetes-dashboard.yaml kubectl create -f ./kubernetes-dashboard.yaml kubectl describe svc kubernetes-dashboard --namespace=kube-system http://10.201 .3.222 :NodePort
Kubernetes应用实例 Kubernetes部署Nginx Kubernetes部署服务一般有两种模式,这里用第2种模式:
先定义RC创建Pod,再定义与之关联的Service
先定义Service,再定义RC来创建Pod
下载镜像
定义RC文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 apiVersion: v1 kind: ReplicationController metadata: name: nginx labels: name: nginx spec: replicas: 2 selector: name: nginx template: metadata: labels: name: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80
kind
表明类型
spec.selector
为RC的Pod选择器,监控和管理拥有此label的Pod实例,确保集群中始终有且仅有replicas个Pod实例运行
spec.template
定义生产Pod实例的模板,此处的labels必须和spec.selector一致
spec.template.spec.containers
指明容器的一些属性
现在Kubernetes推荐使用Deployment
代替RC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx spec: replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
创建Pod & 查看Pod 1 2 3 4 5 6 kubectl create -f nginx.yaml kubectl get pods -o wide
定义Service文件 nginx-service.yaml
创建的Service是无法被外部访问的,要想外部能访问需要创建带有NodePort的Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: v1 kind: Service metadata: name: nginx-service labels: name: nginx-service spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: name: nginx
metadata.name
为Service的名称(ServerName)
spec.selector
表明哪些Pod对应此Service(此处指明拥有nginx labels的Pod属于nginx-service这个Service)
spec.ports.targetPort
具体进程在容器内的端口,spec.ports.port是该Service的端口
nginx-service-nodeport.yaml
创建的Service使用Node节点系统上的Port,可直接通过Node:Port
访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 apiVersion: v1 kind: Service metadata: name: nginx-service-nodeport labels: name: nginx-service-nodeport spec: type : NodePort ports: - port: 80 nodePort: 32222 targetPort: 80 protocol: TCP selector: name: nginx
NodePort 表示使用Node节点上的物理机端口提供外网访问功能
spec.ports.nodePort
端口范围定义必须在30000
~32767
内,故一般可不指定spec.ports.nodePort
而随机分配。然后用kubectl describe svc <service-name>
查看分配的NodePord
查看Service情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 kubectl get svc -o wide kubectl describe svc nginx-service-nodeport
手动扩容RC 1 kubectl scale rc nginx --replicas=<NUMBER>
使用Kubernetes Ingress访问kubernetes Dashboard Ingress是Kubernetes1.2后引入,用于暴露服务用的。在1.2版本前只有LoadBalancer、NodePort两种方式。Ingress利用Nginx/HAProxy等反向代理软件实现所有Service的对外暴露服务,根据域名/URL规则动态将请求转到相应的Service。 这里演示使用Nginx Ingress来反向代理Kubernetes Dashboard。
部署默认后端 一般可部署一个默认后端,用于当域名、URL全都不匹配时候用。default-backend
什么也不做,只返回404
页面。官方提供的default-backend.yaml
1 kubectl create -f default-backend.yaml
部署Ingress Controller Ingress Controller部署方式可选Deployment 或DaemonSet ,这里选择使用DaemonSet 方式部署。官方有个nginx-ingress-daemonset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: nginx-ingress-lb labels: name: nginx-ingress-lb namespace: kube-system spec: template: metadata: labels: name: nginx-ingress-lb annotations: prometheus.io/port: '10254' prometheus.io/scrape: 'true' spec: terminationGracePeriodSeconds: 60 hostNetwork: true containers: - image: gcr.io/google_containers/nginx-ingress-controller:0.9 .0 -beta.5 name: nginx-ingress-lb readinessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 1 ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 443 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace args: - /nginx-ingress-controller - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
创建Nginx Ingress Controller
1 kubectl create -f nginx-ingress-controller.yaml
部署Ingress kind: Ingress
用于创建Ingress资源,设置Nginx Ingress规则(域名/URL)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kubernetes-dashboard-ingress namespace: kube-system spec: rules: - host: your.domain.com http: paths: - backend: serviceName: kubernetes-dashboard servicePort: 80
1 2 3 4 5 kubectl create -f kubernetes-dashboard-ingress.yaml kubectl get ingress -n kube-system
部署成功后直接使用域名http://your.domain.com
访问就能直接跳转到kubernetes-dashboard。
Kubernetes常用命令简录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 kubectl cluster-info kubectl get nodes kubectl get rc kubectl get pods kubectl get pods -o wide kubectl get pods -n kube-system kubectl describe pods <pod-name> kubectl get services kubectl get svc kubectl describe services <service-name> kubectl describe svc <service-name> kubectl exec <pod-name> env kubectl exec -ti <pod-name> -- bash kubectl create -f <xxx.yaml> kubectl delete pods,services -l name=<labels-name> kubectl delete pods --all kubectl stop replicationcontroller foo kubectl stop pods,services -l name=myLabel kubectl stop -f service.json kubectl --namespace=kube-system scale deployment kube-dns --replicas=<NUMBER>