Kuberbetes(九)--使用yaml创建rc

917 阅读7分钟

1.使用yaml创建并启动replicas集合

k8s通过Replication Controller来创建和管理各个不同的重复容器集合(实际上是重复的pods)。

Replication Controller会确保pod的数量在运行的时候会一直保持在一个特殊的数字,即replicas的设置。

apiVersion: v1
kind: ReplicationController
metadata:
  name: my-nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

和定义一个pod的YAML文件相比,不同的只是kind的值为ReplicationController,replicas的值需要指定,pod的相关定义在template中,pod的名字不需要显式地指定,因为它们会在rc中创建并赋予名字

创建rc:

rc可以通过create命令像创建pod一样来创建:
# kubectl create -f ./nginx-rc.yaml
replicationcontrollers/my-nginx

和直接创建pod不一样,rc将会替换因为任何原因而被删除或者停止运行的Pod,比如说pod依赖的节点挂了。所以我们推荐使用rc来创建和管理复杂应用,即使你的应用只要使用到一个pod,在配置文件中忽略replicas字段的设置即可

2、查看Replication Controller的状态

可以通过get命令来查看你创建的rc:
# kubectl get rc
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR    REPLICAS
my-nginx     nginx          nginx      app=nginx   2

这个状态表示,你创建的rc将会确保你一直有两个nginx的副本。

也可以和直接创建Pod一样查看创建的Pod状态信息:

# kubectl get pods
NAME             READY     STATUS    RESTARTS   AGE
my-nginx-065jq   1/1       Running   0          51s
my-nginx-buaiq   1/1       Running   0          51s

3、删除Replication Controller

当你想停止你的应用,

删除你的rc,可以使用:

# kubectl delete rc my-nginx
replicationcontrollers/my-nginx

默认的,这将会删除所有被这个rc管理的pod,如果pod的数量很大,将会花一些时间来完成整个删除动作,如果你想使这些pod停止运行,请指定--cascade=false。 如果你在删除rc之前尝试删除pod,rc将会立即启动新的pod来替换被删除的pod,就像它承诺要做的一样。

4、Labels

k8s使用用户自定义的key-value键值对来区分和标识资源集合(就像rc、pod等资源),这种键值对称为label。 在上面的例子中,定义pod的template字段包含了一个简单定义的label,key的值为app,value的值为nginx。所有被创建的pod都会卸载这个label,可以通过-L参数来查看:

# kubectl get rc my-nginx -L app
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR    REPLICAS   APP
my-nginx11     nginx          nginx      app=nginx111   2          nginx

默认情况下,pod的label会复制到rc的label,同样地,k8s中的所有资源都支持携带label。

更重要的是,pod的label会被用来创建一个selector,用来匹配过滤携带这些label的pods。 你可以通过kubectl get请求这样一个字段来查看template的格式化输出:

# kubectl get rc my-nginx -o template --template="{{.spec.selector}}"
map[app:nginx111]

5.使用labels定位pods

[root@k8s-master ~]# kubectl get pods -l app=nginx11 -o wide
NAME               READY     STATUS    RESTARTS   AGE       IP          NODE
my-nginx11-1r2p4   1/1       Running   0          11m       10.0.6.3    k8s-node-1
my-nginx11-pc4ds   1/1       Running   0          11m       10.0.33.6   k8s-node-2

检查你的Pod的IPs:

# kubectl get pods -l app=nginx -o json | grep podIP
                "podIP": "10.245.0.15",
                "podIP": "10.245.0.14",

6.k8s中连接容器的模型

现在,你已经有了组合的、多份副本的应用,你可以将它连接到一个网络上。在讨论k8s联网的方式之前,有必要和Docker中连接网络的普通方式进行一下比较。

默认情况下,Docker使用主机私有网络,所以容器之间可以互相交互,只要它们在同一台机器上。 为了让Docker容器可以进行跨节点的交流,必须在主机的IP地址上为容器分配端口号,之后通过主机IP和端口将信息转发到容器中。 这样一来,很明显地,容器之间必须谨慎地使用和协调端口号的分配,或者动态分配端口号。

在众多开发者之间协调端口号的分配是十分困难的,会将集群级别之外的复杂问题暴露给用户来处理。

在k8s中,假设Pod之间可以互相交流,无论它们是在哪个宿主机上。 我们赋予每个Pod自己的集群私有IP,如此一来你就不需要明确地在Pod之间创建连接,或者将容器的端口映射到主机的端口中。 这意味着,Pod中的容器可以在主机上使用任意彼此的端口,而且集群中的Pods可以在不使用NAT的方式下连接到其他Pod。

这时,你应该能够通过使用curl来连接任一IP(如果节点之间没有处于同一个子网段,无法使用私有IP进行连接的话,就只能在对应节点上使用对应的IP进行连接测试)。 注意,容器并不是真的在节点上使用80端口,也没有任何的NAT规则来路由流量到Pod中。 这意味着你可以在同样的节点上使用同样的containerPort来运行多个nginx Pod,并且可以在集群上的任何Pod或者节点通过这个IP来连接它们。 和Docker一样,端口仍然可以发布到宿主机的接口上,但是因为这个网络连接模型,这个需求就变得很少了。

7.创建Service:cluster ip

现在,在集群上我们有了一个运行着nginx并且有分配IP地址空间的的Pod。 理论上,你可以直接和这些Pod进行交互,但是当节点挂掉之后会发生什么? 这些Pod会跟着节点挂掉,然后RC会在另外一个健康的节点上重新创建新的Pod来代替,而这些Pod分配的IP地址都会发生变化,对于Service类型的服务来说这是一个难题。

k8s上的Service是抽象的,其定义了一组运行在集群之上的Pod的逻辑集合,这些Pod是重复的,复制出来的,所以提供相同的功能。 当Service被创建,会被分配一个唯一的IP地址(也称为集群IP)。这个地址和Service的生命周期相关联,并且当Service是运行的时候,这个IP不会发生改变。 Pods进行配置来和这个Service进行交互,之后Service将会自动做负载均衡到Service中的Pod。

service    pod
                pod

你可以通过以下的YAML文件来为你的两个nginx容器副本创建一个Service:

$ cat nginxsvc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginxsvc
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: nginx

这个YAML定义创建创建一个Service,带有Label为app=nginx的Pod都将会开放80端口,并将其关联到一个抽象的Service端口。 (targetPort字段是指容器内开放的端口Service通过这个端口连接Pod,port字段是指抽象Service的端口,nodePort为节点上暴露的端口号,不指定的话为随机。)

现在查看你创建的Service:

[root@k8s-master ~]# kubectl get svc
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.254.0.1      <none>        443/TCP   6d
nginxsvc     10.254.15.142   <none>        80/TCP    17m

和之前提到的一样,Service是以一组Pod为基础的。 这些Pod通过endpoints字段开放出来。 Service的selector将会不断地进行Pod的Label匹配,结果将会通知一个Endpoints Object,这里创建的也叫做nginxsvc。 当Pod挂掉之后,将会自动从Endpoints中移除,当有新的Pod被Service的selector匹配到之后将会自动加入这个Endpoints。 你可以查看这个Endpoint,注意,这些IP和第一步中创建Pods的时候是一样的:

[root@k8s-master ~]# kubectl describe svc nginxsvc
Name:			nginxsvc
Namespace:		default
Labels:			app=nginx11
Selector:		app=nginx111
Type:			ClusterIP
IP:			10.254.15.142
Port:			<unset>	80/TCP
Endpoints:		10.0.33.6:80,10.0.6.3:80
Session Affinity:	None
No events.

[root@k8s-master ~]# kubectl get ep
NAME         ENDPOINTS                  AGE
kubernetes   192.168.245.250:6443       6d
nginxsvc     10.0.33.6:80,10.0.6.3:80   19m

你现在应该可以通过10.254.15.142:80这个IP从集群上的任何一个节点(node)使用curl命令来连接到nginx的Service。

删除service:

#kubectl delete service service名