容器编排Kubernetes,是课程第九章的内容

1.Kubenetes简介

k8s

1.1为什么简写是k8s

因为kubernetes,k和s之间一共有8个字母

2.Minikube快速搭建K8S单节点环境

2.1配置K8S环境

  1. https://github.com/kelseyhightower/kubernetes-the-hard-way 这个是k8s的从头开始安装的方法
  2. https://github.com/kubernetes/minikube 这个是在本地跑一个最简单的k8s,只有一个节点。类似vagrant,是要借助virtual box这种的

2.2安装kubetcl

https://kubernetes.io/docs/tasks/tools/install-kubectl/

2.3minikube

minikube相关命令:

  1. minikube start,启动minikube节点
  2. minikube ssh,连接到minikube内部
  3. minikube stop

2.4kubectl

kubectl context:
里面存着一个kubernetes集群的信息,比如集群的host。kubectl下可能有多个context,我们可以通过context去管理多个k8s集群

相关命令:

  1. kubectl config view
  2. kubectl config get-contexts,得到现在是用的哪个context
  3. kubectl cluster-info,得到集群信息
  4. kubectl version

3.K8S最小调度单位Pod

k8s不对容器进行操作,因为最小单位是pod。同一个pod里面的容器,是在一个namespace下的,这里的namespace包括所有的namespace(如network namespace)

相关命令:

  • kubectl create -f pod_nginx.yml,创建pod
  • kubectl delete -f pod_nginx.yml,删除pod
  • kubectl get pods,查看pods的情况
  • kubectl get pods -o wide,加了wide参数之后,会显示更多信息
  • 上面的命令,可以看到pod里面的容器具体是在哪个机器上的,要进入这个容器,我们先ssh到这个机器上,然后docker exec -it container_name sh,
  • kubectl describe pods nginx,查看pods的具体信息
  • kubectl port-forward nginx 8080:80,映射本地的8080端口和pod的80端口,nginx是pod name,但是要注意的是,这个命令一旦ctrl+c退出,映射就结束了。8080端口是运行了kubectl的机器的端口,不是pod所在的容器的端口。

pod_nginx.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx #使用的镜像
    ports:
    - containerPort: 80

NOTICE

kubectl create之后,可能pod会一直不启动,这个时候可以通过minikube logs查看错误日志。我遇到的问题的是不能拉取镜像,是要翻墙的网址。 解决这个问题可以在启动minikube的时候,指定代理:

1
2
minikube start --docker-env=HTTP_PROXY=http://$YOURPROXY:PORT \
                 --docker-env=HTTPS_PROXY=https://$YOURPROXY:PORT

参考资料:https://github.com/kubernetes/minikube/blob/master/docs/http_proxy.md

4.ReplicaSet和ReplicationController

ReplicaSet是新一代的ReplicationController。这里的replica就是我们之前docker里面遇到的是一样的。也是多个,这里就是多个pod。下面简称rc或者rs

相关命令:

  • kubectl create -f rc_nginx.yml,创建replicationController,rc_nginx.yml见docker_labs
  • kubectl get rc,可以查看rc的情况
  • kubectl get pods,查看pod的情况
  • kubectl delete pods nginx-6cznp,删除这个一个pod
  • kubectl scale rc nginx –replicas=2,修改rc的pod数量
  • kubectl delete rc nginx,删除replicationController -kubectl create -f rs_nginx.yml,创建replicaSet,ns_nginx.yml见docker-labs
  • kubectl get rs,查看rs的情况
  • kubectl scale rs nginx –replicas=2,对rs进行scale

rc_nginx.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx #使用nginx镜像
        ports:
        - containerPort: 80

rs_nginx.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
  labels:
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      name: nginx
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx
        image: nginx #使用nginx镜像
        ports:
        - containerPort: 80

NOTICE

要是我们在rc或者rs下创建pod,然后我们去强制删除这个pod,删除之后,rc和rs会自动再去创建一个pod。rc和rs会保持pod的数量,所以就算只创建一个pod,也推荐使用rc或者rs。因为这会保持pod的数量。

5.Deployment

Deployment描述了一种希望的状态,是对pods和replicaset的希望达到的一个状态。比如我希望这个replicaset是有3个replica的,pods的image是nginx。之后我们要修改的话,只要把希望的状态改变,deployment就会自动帮我们完成。 需要注意的是,我们通过deployment创建的replicaset和pod,创建了之后,我们就不能独立的对replicaset和pod进行删除了,我们一定要对deployment进行操作

相关命令:

  1. kubectl create -f deployment_nginx.yml,创建deployment,详见docker-lab
  2. kubectl get deployment,得到deployment的情况
  3. kubectl get deployment -o wide,得到详细情况
  4. kubectl set image deployment nginx-deployment nginx=nginx:1.13,更新镜像,nginx-deployment是deployment的name,nginx:1.13是新的镜像
  5. kubectl rollout history deployment nginx-deployment,查看deployment的历史版本
  6. kubectl rollout undo deployment nginx-deployment,撤销之前的操作,比如我们先更新了一个镜像,然后我们使用undo,就会变回原来的镜像了
  7. kubectl get node -o wide,查看k8s node的情况
  8. kubectl expose deployment nginx-deployment –type=NodePort,会暴露到node的一个随机端口上,是暴露到最终运行pod的机器上,不是运行kubectl的机器上,具体可以看9-8
  9. kubectl get services,查看services的情况,因为我们用了8的命令,所以service会随机一个端口绑定到容器的80端口。是绑定到最终运行pod的node上的,不是运行kubectl的机器
  10. kubectl delete service nginx-deployment,删除service

deployment_nginx.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.12.2 #先指定这个版本的nginx,之后可以更新
        ports:
        - containerPort: 80

NOTICE

deployment下的replicaset和pods的name,replicaset的前缀是deployment的name,pods的name的前缀是replicaset的name

6.使用Tectonic在本地搭建多节点K8S集群

tectonic的脚本详见docker-lab,要注意的是,vagrant up的时候用的脚本,访问的基本都是被墙的网址,在脚本里面设置代理很麻烦,我最后是直接在路由器上安装了代理,才安装好。

相关命令:

  1. kubectl config get-contexts,查看kubectl的context
  2. kubectl config use-context tectonic,切换到tectonic这个context

NOTICE

我一开始用kubectl_1.11的版本使用命令kubectl get nodes的时候,会返回错误,然后我就用了kubectl的1.8这个版本,就正确了。

参考资料:https://github.com/kubernetes/kubernetes/issues/65575

7.k8s基础网络Cluster Network

k8s_network

这个flannel其实是一个k8s的网络插件,也可以不用flannel,可以用的别的网络插件。 k8s的网络插件,要符合最基本的3个规则,详见:
https://kubernetes.io/docs/concepts/cluster-administration/networking/

8.Service简介和演示

8.1不要直接使用和管理Pods

pods

这里创建新的pods倒是没问题,但是最关键的是,新创建的pod可能ip会变。我们现在打个比方,我有两个pod,一个是nginx,还有一个是db,现在我db的pod被terminated然后创建了一个新的。这个时候要是db的ip变了,nginx是没办法修改的。所以我们需要用到service来解决这个问题,service就会给一个不变的ip和pod的ip相当于映射住,service的ip是不变的。那我们访问service的ip就可以了。然后我们要是用deployment这种,replica设成多个,我们可以在deployment上创建service,那么这个service会自动帮我们在多个replica之间做负载均衡。

8.2Service

services

本节课说的是ClusterIP的,这种service是在cluster内部,任何一台机器都可以访问的,但是也仅限于cluster内部

相关命令:

  1. kubectl expose pods nginx-pod,创建service,默认是ClusterIP
  2. kubectl get svc/services,svc是简写
  3. kubectl expose deployment service-test,在deployment上创建一个service,会为deployment里面的pods自动做负载均衡
  4. kubectl edit deployment service-test,这样可以更新service-test这个deployment的配置,然后k8s会帮我们自己更新

9.NodePort类型Service以及Label的简单实用

9.1NodePort类型Service

创建NodePort的service,有两种方式,一种用命令创建,一种是用yml文件来创建。 NodePort是可以给外网访问的,而且是集群内,所有node的ip加上这个service的port都可以访问。NodePort的端口是有范围的,是从30000-32767

用命令创建:

  1. kubectl create -f pod_nginx.yml,创建pod_nginx,yml见docker-lab
  2. kubectl expose pods nginx-pod –type=NodePort,创建NodePort的service
  3. kubectl get svc,查看创建的sevice,注意,在service我们会看到NodePort类型的service,会随机一个端口映射到pod的端口。这个时候所有node的ip+这个端口,就可以访问pod

用文件创建:

pod_nginx.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - name: nginx-port #这个name,service_nginx.yml里面会使用到
      containerPort: 80

service_nginx.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 32333
    nodePort: 32333
    targetPort: nginx-port #pod_nginx.yml里面的ports下的name
    protocol: TCP
  selector:
    app: nginx # label
  type: NodePort
  1. targetPort后面要跟pod的yml文件里面的ports下的name
  2. selector后面的值是label的key和value,通过这个值去选择有这个label的pod去创建这个service

9.2Label

k8s里面,几乎所有的resource,如pod,deployment等等,我们都可以设置标签。比如我们可以指定nodeSelector,那么我们在创建pod的时候,就可以指定我们这个pod是要创建在哪个node上。

相关命令:

  1. kubectl label node w1.tectonicsandbox.com hardware=good,这个就是给w1这个node添加了一个label
  2. kubectl get node –show-labels,可以查看label

NOTICE

  1. 在生产环境里面,ClusterIP因为只能在cluster内部访问,外部是不能访问的,所以不会用。NodePort的端口又是有限的,所以一般也不会使用,但是是可以使用的。
  2. NodePort的端口是有范围的,是从30000-32767

10.准备工作——使用kops在亚马逊AWS上搭建k8s集群

kops: https://github.com/kubernetes/kops

11.使用kops在亚马逊AWS上搭建k8s集群

使用kops,在AWS创建k8s集群

12.LoadBlancer类型Service以及AWS的DNS服务配置

service里面还有一个类型是,loadblancer,这个类型是需要云服务商的支持的,本地是没法测试的。这个service会给出一个url,然后加上给出的端口就可以访问了。因为这个url会很长,所以我们还可以使用dns来添加ANAME来映射到一个短的sub domain

13.在亚马逊k8s集群上部署wordpress