Kubernetes(k8s)入门:核心组件详解

这篇具有很好参考价值的文章主要介绍了Kubernetes(k8s)入门:核心组件详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

附:集群搭建请移步:
Kubernetes(k8s)集群搭建,完整无坑,不需要科学上网~

Controllers官网文档:https://kubernetes.io/docs/concepts/workloads/controllers/

一、ReplicationController(RC)

1、官方解释

官网:https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/

官网原文:A ReplicationController ensures that a specified number of pod replicas are running at any one time. In other words, a ReplicationController makes sure that a pod or a homogeneous set of pods is always up and available.

ReplicationController定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,所以RC的定义包含以下几个部分:

  • Pod期待的副本数(replicas)
  • 用于筛选目标Pod的Label Selector
  • 当Pod的副本数量小于预期数量时,用于创建新Pod的Pod模板(template)

也就是说通过RC实现了集群中Pod的高可用,减少了传统IT环境中手工运维的工作。

2、举个例子

(1)创建名为nginx_replication.yaml

kind:表示要新建对象的类型
spec.selector:表示需要管理的Pod的label,这里表示包含app: nginx的label的Pod都会被该RC管理
spec.replicas:表示受此RC管理的Pod需要运行的副本数,永远保持副本数为这个数量
spec.template:表示用于定义Pod的模板,比如Pod名称、拥有的label以及Pod中运行的应用等
通过改变RC里Pod模板中的镜像版本,可以实现Pod的升级功能

kubectl apply -f nginx_replication.yaml,此时k8s会在所有可用的Node上,创建3个Pod,并且每个Pod都有一个app: nginx的label,同时每个Pod中都运行了一个nginx容器。
如果某个Pod发生问题,Controller Manager能够及时发现,然后根据RC的定义,创建一个新的Pod
扩缩容:kubectl scale rc nginx --replicas=5

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
        ports:
        - containerPort: 80
# 编辑yaml文件
[root@m ~]# vi nginx_replication.yaml
# 创建pod
[root@m ~]# kubectl apply -f nginx_replication.yaml
replicationcontroller/nginx created
# 获取pod信息
[root@m ~]# kubectl get pods
NAME          READY   STATUS              RESTARTS   AGE
nginx-2fw2t   0/1     ContainerCreating   0          15s
nginx-hqcwh   0/1     ContainerCreating   0          15s
nginx-sks62   0/1     ContainerCreating   0          15s
# 查看详细信息
[root@m ~]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP               NODE   NOMINATED NODE   READINESS GATES
nginx-2fw2t   1/1     Running   0          75s   192.168.80.196   w2     <none>           <none>
nginx-hqcwh   1/1     Running   0          75s   192.168.190.68   w1     <none>           <none>
nginx-sks62   1/1     Running   0          75s   192.168.190.67   w1     <none>           <none>

# 删除指定pod(会自动重启,永远保持副本数不变,即使宕机也会重启)
kubectl delete pods nginx-2fw2t
kubectl get pods

# 扩容为5个
kubectl scale rc nginx --replicas=5
kubectl get pods
nginx-8fctt   0/1     ContainerCreating   0          2s
nginx-9pgwk   0/1     ContainerCreating   0          2s
nginx-hksg8   1/1     Running             0          6m50s
nginx-q7bw5   1/1     Running             0          6m50s
nginx-wzqkf   1/1     Running             0          99s
# 删除pod,必须通过yaml文件进行删除
kubectl delete -f nginx_replication.yaml

3、小总结

ReplicationController通过selector来管理template(pod),selector中的key-value需要对应template中的labels,否则会找不到。

同时支持扩缩容,副本数永远保持不变。

二、ReplicaSet(RS)

1、官方解释

官网:https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/

官网原文:A ReplicaSet’s purpose is to maintain a stable set of replica Pods running at any given time. As such, it is often used to guarantee the availability of a specified number of identical Pods.

在Kubernetes v1.2时,RC就升级成了另外一个概念:Replica Set,官方解释为“下一代RC”

ReplicaSet和RC没有本质的区别,kubectl中绝大部分作用于RC的命令同样适用于RS

RS与RC唯一的区别是:RS支持基于集合的Label Selector(Set-based selector),而RC只支持基于等式的Label Selector(equality-based selector),这使得Replica Set的功能更强

2、举个例子

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  matchLabels: 
    tier: frontend
  matchExpressions: 
    - {key:tier,operator: In,values: [frontend]}
  template:
  ...

操作与ReplicationController(RC)一致,注意:一般情况下,我们很少单独使用Replica Set,它主要是被Deployment这个更高的资源对象所使用,从而形成一整套Pod创建、删除、更新的编排机制。当我们使用Deployment时,无须关心它是如何创建和维护Replica Set的,这一切都是自动发生的。同时,无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。

三、Deployment(用的最多)

1、官方解释

官网:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

A Deployment provides declarative updates for Pods and ReplicaSets.

You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.

Deployment相对RC最大的一个升级就是我们可以随时知道当前Pod“部署”的进度。

Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

2、举个例子

创建一个Deployment对象来生成对应的Replica Set并完成Pod副本的创建过程,检查Deploymnet的状态来看部署动作是否完成(Pod副本的数量是否达到预期的值)

永远保持pod为3个,并且随时可以知道pod的部署进度!

(1)创建nginx_deployment.yaml文件

apiVersion: apps/v1 # 版本
kind: Deployment # 类型
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3 # 副本数
  selector: # selector 匹配pod的lebel
    matchLabels:
      app: nginx
  template: # pod
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
# 根据nginx_deployment.yaml文件创建pod
[root@m ~]# kubectl apply -f nginx_deployment.yaml
deployment.apps/nginx-deployment created

# 查看pod
[root@m ~]# kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP               NODE   NOMINATED NODE   READINESS GATES
nginx-deployment-6dd86d77d-6q66c   1/1     Running   0          75s   192.168.190.70   w1     <none>           <none>
nginx-deployment-6dd86d77d-f98jt   1/1     Running   0          75s   192.168.80.199   w2     <none>           <none>
nginx-deployment-6dd86d77d-wcxlf   1/1     Running   0          75s   192.168.80.198   w2     <none>           <none>

# 查看deployment
[root@m ~]# kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/3     3            0           18s
# 查看ReplicaSet
[root@m ~]# kubectl get rs
NAME                         DESIRED   CURRENT   READY   AGE
nginx-deployment-6dd86d77d   3         3         0       23s
[root@m ~]# kubectl get deployment -o wide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES        SELECTOR
nginx-deployment   0/3     3            0           29s   nginx        nginx:1.7.9   app=nginx

(2)版本滚动更新

# 当前nginx的版本
[root@m ~]# kubectl get deployment -o wide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES        SELECTOR
nginx-deployment   3/3     3            3           2m36s   nginx        nginx:1.7.9   app=nginx

# 更新nginx的image版本
[root@m ~]# kubectl set image deployment nginx-deployment nginx=nginx:1.9.1
deployment.extensions/nginx-deployment image updated

# 查看更新后的版本
[root@m ~]# kubectl get deployment -o wide
NAME               READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES        SELECTOR
nginx-deployment   3/3     1            3           3m21s   nginx        nginx:1.9.1   app=nginx

# 发现之前的版本已经被删了,新版本是启动状态
[root@m ~]# kubectl get rs -o wide
NAME                          DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES        SELECTOR
nginx-deployment-6dd86d77d    0         0         0       4m41s   nginx        nginx:1.7.9   app=nginx,pod-template-hash=6dd86d77d
nginx-deployment-784b7cc96d   3         3         3       96s     nginx        nginx:1.9.1   app=nginx,pod-template-hash=784b7cc96d

3、注意事项

通常来说我们使用Deployment只管理一个pod,也就是一个应用。

四、Labels and Selectors

1、官方解释

label,顾名思义,就是给一些资源打上标签的,由key-value键值对组成。

官网:https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/

官方解释:Labels are key/value pairs that are attached to objects, such as pods.

2、举个例子

表示名称为nginx-deployment的pod,有一个label,key为app,value为nginx。

我们可以将具有同一个label的pod,交给selector管理

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:             # 匹配具有同一个label属性的pod标签
    matchLabels:
      app: nginx         
  template:             # 定义pod的模板
    metadata:
      labels:
        app: nginx      # 定义当前pod的label属性,app为key,value为nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
# 查看pod的label标签
[root@m ~]# kubectl get pods --show-labels
NAME                                READY   STATUS    RESTARTS   AGE     LABELS
nginx-deployment-784b7cc96d-25js4   1/1     Running   0          4m39s   app=nginx,pod-template-hash=784b7cc96d
nginx-deployment-784b7cc96d-792lj   1/1     Running   0          5m24s   app=nginx,pod-template-hash=784b7cc96d
nginx-deployment-784b7cc96d-h5x2k   1/1     Running   0          3m54s   app=nginx,pod-template-hash=784b7cc96d

五、Namespace

1、什么是Namespace

[root@m ~]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-784b7cc96d-25js4   1/1     Running   0          8m19s
nginx-deployment-784b7cc96d-792lj   1/1     Running   0          9m4s
nginx-deployment-784b7cc96d-h5x2k   1/1     Running   0          7m34s
[root@m ~]# kubectl get pods -n kube-system
NAME                                      READY   STATUS    RESTARTS   AGE
calico-kube-controllers-f67d5b96f-7p9cg   1/1     Running   2          17h
calico-node-6pvpg                         1/1     Running   0          141m
calico-node-m9d5l                         1/1     Running   0          141m
calico-node-pvvt8                         1/1     Running   2          17h
coredns-fb8b8dccf-bbvtp                   1/1     Running   2          17h
coredns-fb8b8dccf-hhfb5                   1/1     Running   2          17h
etcd-m                                    1/1     Running   2          17h
kube-apiserver-m                          1/1     Running   2          17h
kube-controller-manager-m                 1/1     Running   2          17h
kube-proxy-5hmwn                          1/1     Running   0          141m
kube-proxy-bv4z4                          1/1     Running   0          141m
kube-proxy-rn8sq                          1/1     Running   2          17h
kube-scheduler-m                          1/1     Running   2          17h

上面我们查看的pod是不一样的,因为这些pod分属不同的Namespace。

# 查看一下当前的命名空间
[root@m ~]# kubectl get namespaces
NAME              STATUS   AGE
default           Active   17h
kube-node-lease   Active   17h
kube-public       Active   17h
kube-system       Active   17h

其实说白了,命名空间就是为了隔离不同的资源,比如:Pod、Service、Deployment等。可以在输入命令的时候指定命名空间-n,如果不指定,则使用默认的命名空间:default。

2、创建命名空间

创建myns-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: myns
# 创建namespace
kubectl apply -f myns-namespace.yaml

# 查看namespace列表使用kubectl get ns也可以
[root@m ~]# kubectl get namespaces
NAME              STATUS   AGE
default           Active   17h
kube-node-lease   Active   17h
kube-public       Active   17h
kube-system       Active   17h
myns              Active   11s

3、创建指定命名空间下的pod

# 比如创建一个pod,属于myns命名空间下
vi nginx-pod.yaml
kubectl apply -f nginx-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: myns
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
#查看myns命名空间下的Pod和资源
# 默认查看default namespace
kubectl get pods
# 指定namespace
kubectl get pods -n myns
kubectl get all -n myns
kubectl get pods --all-namespaces    #查找所有命名空间下的pod

六、Network

1、回顾docker的网络

(1)单机docker

在单机docker中,容器与容器之间网络通讯是通过网络桥进行连接的。
docker网络详解,自定义docker网络
Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

(2)docker-swarm 多机集群

当docker-swarm 多机集群下,是如何通信的呢?通过overlay网络,将数据包通过互联网进行传输。
Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

(3)k8s中pod网络

k8s里面,又将网络提高了一个复杂度。

我们都知道K8S最小的操作单位是Pod,先思考一下同一个Pod中多个容器要进行通信,是可以的吗?
由官网的这段话可以看出,同一个pod中的容器是共享网络ip地址和端口号的,通信显然没问题:

Each Pod is assigned a unique IP address. Every container in a Pod shares the network namespace, including the IP address and network ports.

那如果是通过容器的名称进行通信呢?就需要将所有pod中的容器加入到同一个容器的网络中,我们把该容器称作为pod中的pause container。
Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器
我们发现,每个pod中都会有一个pause container,所有创建的container都会连接到它上面。

[root@w1 ~]# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
559a6e5ab486        94ec7e53edfc           "nginx -g 'daemon of…"   2 hours ago         Up 2 hours                              k8s_nginx_nginx-deployment-784b7cc96d-h5x2k_default_f730b118-1a17-11ee-ad40-5254004d77d3_0
60f048b660b1        k8s.gcr.io/pause:3.1   "/pause"                 2 hours ago         Up 2 hours 

Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

2、集群内Pod与Node之间的通信

(1)案例分析

我们准备一个nginx-pod、一个busybox-pod:

# nginx_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
# busybox_pod.yaml
apiVersion: v1
kind: Pod
metadata:
 name: busybox
 labels:
    app: busybox
spec:
 containers:
  - name: busybox
    image: busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
# 将两个pod运行起来,并且查看运行情况
kubectl apply -f nginx_pod.yaml
kubectl apply -f busybox_pod.yaml
[root@m ~]# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE     IP               NODE   NOMINATED NODE   READINESS GATES
busybox     1/1     Running   0          2m1s    192.168.190.73   w1     <none>           <none>
nginx-pod   1/1     Running   0          2m25s   192.168.80.201   w2     <none>           <none>

我们发现,两个应用分别部署在了w1节点和w2节点,各自生成了一个ip:192.168.190.73、 192.168.80.201

而且,不管在master节点还是worker节点,访问任意一个pod都是可以访问通的。这就是网络插件(比如calico)的功劳,它不光帮我们生成了pod的ip,并且将这些pod之间的网络也都处理好了。

但是这个ip,只限于集群内访问

(2)How to implement the Kubernetes Cluster networking model–Calico

官网:https://kubernetes.io/docs/concepts/cluster-administration/networking/#the-kubernetes-network-model

  • pods on a node can communicate with all pods on all nodes without NAT
  • agents on a node (e.g. system daemons, kubelet) can communicate with all pods on that node
  • pods in the host network of a node can communicate with all pods on all nodes without NAT

得益于这个网络插件,集群内部不管是pod访问pod,还是pod访问node,还是node访问pod,都是可以成功的。

3、集群内Service-Cluster IP

对于上述的Pod虽然实现了集群内部互相通信,但是Pod是不稳定的,比如通过Deployment管理Pod,随时可能对Pod进行扩缩容,这时候Pod的IP地址是变化的

我们希望能够有一个固定的IP,使得集群内能够访问。也就是能够把相同或者具有关联的Pod,打上Label,组成Service。而Service有固定的IP,不管Pod怎么创建和销毁,都可以通过Service的IP进行访问。

Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

(1)官方描述

Service官网:https://kubernetes.io/docs/concepts/services-networking/service/

An abstract way to expose an application running on a set of Pods as a network service.
With Kubernetes you don’t need to modify your application to use an unfamiliar service discovery mechanism. Kubernetes gives Pods their own IP addresses and a single DNS name for a set of Pods, and can load-balance across them.

可以将Service理解为一个nginx。

(2)举个例子:pod地址不稳定

创建whoami-deployment.yaml文件,并且apply

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deployment
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: jwilder/whoami
        ports:
        - containerPort: 8000
# 创建
kubectl apply -f whoami-deployment.yaml
# 查看详细信息
[root@m ~]# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE    IP               NODE   NOMINATED NODE   READINESS GATES
whoami-deployment-678b64444d-6wltg   1/1     Running   0          100s   192.168.80.202   w2     <none>           <none>
whoami-deployment-678b64444d-cjpzr   1/1     Running   0          100s   192.168.190.74   w1     <none>           <none>
whoami-deployment-678b64444d-v7zfg   1/1     Running   0          100s   192.168.80.203   w2     <none>           <none>
# 删除一个pod
[root@m ~]# kubectl delete pod whoami-deployment-678b64444d-6wltg
pod "whoami-deployment-678b64444d-6wltg" deleted
# 会自动又生成一个pod,但是地址明显变化了
[root@m ~]# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE   NOMINATED NODE   READINESS GATES
whoami-deployment-678b64444d-cjpzr   1/1     Running   0          2m59s   192.168.190.74   w1     <none>           <none>
whoami-deployment-678b64444d-l4dgz   1/1     Running   0          20s     192.168.190.75   w1     <none>           <none>
whoami-deployment-678b64444d-v7zfg   1/1     Running   0          2m59s   192.168.80.203   w2     <none>           <none>

我们通过测试发现,pod的地址确实是一直在变化着的,并不稳定。

(3)创建service

# 查看当前service,默认只有一个kubernetes的service
[root@m ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   20h
# 创建一个service
[root@m ~]# kubectl expose deployment whoami-deployment
service/whoami-deployment exposed
# 查看当前service
[root@m ~]# kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP    20h
whoami-deployment   ClusterIP   10.109.104.247   <none>        8000/TCP   9s

# 删除service
#kubectl delete service whoami-deployment

此时我们创建的service,也有一个cluster-ip,我们尝试访问这个ip,发现可以访问whoami的这三个node,并且自动做了负载均衡:

[root@m ~]# curl 10.109.104.247:8000
I'm whoami-deployment-678b64444d-l4dgz
[root@m ~]# curl 10.109.104.247:8000
I'm whoami-deployment-678b64444d-cjpzr
[root@m ~]# curl 10.109.104.247:8000
I'm whoami-deployment-678b64444d-v7zfg

(4)查看service详细信息

[root@m ~]# kubectl describe svc whoami-deployment
Name:              whoami-deployment
Namespace:         default
Labels:            app=whoami
Annotations:       <none>
Selector:          app=whoami
Type:              ClusterIP
IP:                10.109.104.247
Port:              <unset>  8000/TCP
TargetPort:        8000/TCP
Endpoints:         192.168.190.74:8000,192.168.190.75:8000,192.168.80.203:8000
Session Affinity:  None
Events:            <none>

我们发现,下面挂在了三个pod,此时我们扩容一下:

# 扩容
kubectl scale deployment whoami-deployment --replicas=5
[root@m ~]# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE   NOMINATED NODE   READINESS GATES
whoami-deployment-678b64444d-btvm4   1/1     Running   0          27s   192.168.80.204   w2     <none>           <none>
whoami-deployment-678b64444d-cjpzr   1/1     Running   0          14m   192.168.190.74   w1     <none>           <none>
whoami-deployment-678b64444d-l4dgz   1/1     Running   0          11m   192.168.190.75   w1     <none>           <none>
whoami-deployment-678b64444d-nfg4b   1/1     Running   0          27s   192.168.190.76   w1     <none>           <none>
whoami-deployment-678b64444d-v7zfg   1/1     Running   0          14m   192.168.80.203   w2     <none>           <none>

此时再查看service详细信息:

[root@m ~]# kubectl describe svc whoami-deployment
Name:              whoami-deployment
Namespace:         default
Labels:            app=whoami
Annotations:       <none>
Selector:          app=whoami
Type:              ClusterIP
IP:                10.109.104.247
Port:              <unset>  8000/TCP
TargetPort:        8000/TCP
Endpoints:         192.168.190.74:8000,192.168.190.75:8000,192.168.190.76:8000 + 2 more...
Session Affinity:  None
Events:            <none>

我们发现,service的ip,在集群内任意节点和pod也都能够访问(外网不能访问)。

(5)使用yaml创建service

其实对于Service的创建,不仅仅可以使用kubectl expose,也可以定义一个yaml文件

apiVersion: v1
kind: Service # 类型
metadata:
  name: my-service # name
spec:
  selector:
    app: MyApp # 对应deployment的selector与label
  ports:
    - protocol: TCP
      port: 80 # service自己的端口
      targetPort: 9376 # 目标端口,对应deployment的端口
  type: Cluster

(6)小总结

其实Service存在的意义就是为了Pod的不稳定性,而上述探讨的就是关于Service的一种类型Cluster IP,只能供集群内访问。

4、外部服务访问集群中的pod:Service-NodePort(不推荐)

相当于在Node节点上,对外暴露一个端口,这个端口与pod服务进行绑定。
Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

(1)举个例子

根据whoami-deployment.yaml创建pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deployment
  labels:
    app: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: jwilder/whoami
        ports:
        - containerPort: 8000
# 创建
kubectl apply -f whoami-deployment.yaml
# 查看详细信息
[root@m ~]# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE   NOMINATED NODE   READINESS GATES
whoami-deployment-678b64444d-cn462   1/1     Running   0          10s   192.168.80.206   w2     <none>           <none>
whoami-deployment-678b64444d-j8r7f   1/1     Running   0          10s   192.168.190.77   w1     <none>           <none>
whoami-deployment-678b64444d-wwl47   1/1     Running   0          10s   192.168.80.205   w2     <none>           <none>
# 创建一个NodePort类型的service
[root@m ~]# kubectl expose deployment whoami-deployment --type=NodePort
service/whoami-deployment exposed
# 查看service
[root@m ~]# kubectl get svc
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP          21h
whoami-deployment   NodePort    10.100.197.231   <none>        8000:31222/TCP   6s

我们发现,这个service的类型就是NodePort 了,仍然有一个cluster-ip,在集群内部使用这个cluster-ip仍然是可用的:

[root@m ~]# curl 10.100.197.231:8000
I'm whoami-deployment-678b64444d-j8r7f
[root@m ~]# curl 10.100.197.231:8000
I'm whoami-deployment-678b64444d-wwl47
[root@m ~]# curl 10.100.197.231:8000
I'm whoami-deployment-678b64444d-cn462

我们还发现PORT那一栏,有这样的一个标识:8000:31222/TCP,说明8000端口已经被映射到了31222端口。

我们可以从外界来访问集群内部的服务了。

(2)总结

使用NodePort的方式可以实现外部服务访问集群中的pod,但是端口占用太多,生产不推荐使用。

[root@m ~]# kubectl delete -f whoami-deployment.yaml 
deployment.apps "whoami-deployment" deleted
[root@m ~]# kubectl delete svc whoami-deployment
service "whoami-deployment" deleted

(3)使用yaml文件一键部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  labels:
    app: tomcat
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 80   
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat
  type: NodePort  
vi my-tomcat.yaml

kubectl apply -f my-tomcat.yaml

kubectl get pods -o wide

kubectl get deployment

kubectl get svc

浏览器想要访问这个tomcat,也就是外部要访问该tomcat,用之前的Service-NodePort的方式是可以的,比如暴露一个32008端口,只需要访问192.168.0.61:32008即可。

Service-NodePort的方式生产环境不推荐使用。

5、外部服务访问集群中的pod:Service-LoadBalance(不推荐)

Service-LoadBalance通常需要第三方云提供商支持,有约束性,我们也不推荐使用

6、外部服务访问集群中的pod:Ingress(推荐)

(1)官网解释

官网:https://kubernetes.io/docs/concepts/services-networking/ingress/

An API object that manages external access to the services in a cluster, typically HTTP.
Ingress can provide load balancing, SSL termination and name-based virtual hosting.

Ingress就是帮助我们访问集群内的服务的。

官网Ingress:https://kubernetes.io/docs/concepts/services-networking/ingress/

GitHub Ingress Nginx:https://github.com/kubernetes/ingress-nginx

Nginx Ingress Controller:https://kubernetes.github.io/ingress-nginx/
Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

(2)举个例子

① 先删除之前的tomcat及service
# 先删除之前的tomcat及service
kubectl delete -f my-tomcat.yaml
② 部署tomcat
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  labels:
    app: tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  ports:
  - port: 80   
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat
# 部署tomcat
vi tomcat.yaml
kubectl apply -f tomcat.yaml
[root@m ~]# kubectl get pods -o wide
NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE   NOMINATED NODE   READINESS GATES
tomcat-deployment-6b9d6f8547-6d4z4   1/1     Running   0          2m22s   192.168.80.208   w2     <none>           <none>
[root@m ~]# kubectl get svc
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP   22h
tomcat-service   ClusterIP   10.102.167.248   <none>        80/TCP    2m36s

此时,集群内访问tomcat是可以访问的:

curl 192.168.80.208:8080
curl 10.102.167.248
③ 部署ingress-controller

通过NodePort的方式会占用所有节点的主机端口,我们使用ingress的方式只需要指定一台主机端口即可。

# 确保nginx-controller运行到w1节点上
kubectl label node w1 name=ingress

# 使用HostPort方式运行,需要增加配置(看下图)
#hostNetwork: true

# 搜索nodeSelector,并且要确保w1节点上的80和443端口没有被占用,镜像拉取需要较长的时间,这块注意一下哦
kubectl apply -f mandatory.yaml

kubectl get all -n ingress-nginx

Kubernetes(k8s)入门:核心组件详解,云原生,kubernetes,docker,容器

# mandatory.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      hostNetwork: true
      nodeSelector:
        name: ingress
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

---

# 通过我们的配置,一定是部署在w1节点上的
[root@m ~]# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-7c66dcdd6c-qrgpg   1/1     Running   0          113s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress-controller   1/1     1            1           113s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-controller-7c66dcdd6c   1         1         1       113s
[root@m ~]# kubectl get pods -o wide -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE    IP               NODE   NOMINATED NODE   READINESS GATES
nginx-ingress-controller-7c66dcdd6c-qrgpg   1/1     Running   0          116s   192.168.56.101   w1     <none>           <none>

此时,w1节点的80、443端口就打通了。

④ 创建ingress并定义转发规则
#nginx-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
  - host: tomcat.cxf.com # 域名
    http:
      paths:
      - path: /
        backend:
          serviceName: tomcat-service
          servicePort: 80
# 创建ingress
kubectl apply -f nginx-ingress.yaml

[root@m ~]# kubectl get ingress
NAME            HOSTS            ADDRESS   PORTS   AGE
nginx-ingress   tomcat.cxf.com             80      18s
[root@m ~]# kubectl describe ingress nginx-ingress
Name:             nginx-ingress
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host            Path  Backends
  ----            ----  --------
  tomcat.cxf.com  
                  /   tomcat-service:80 (192.168.80.208:8080)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"nginx-ingress","namespace":"default"},"spec":{"rules":[{"host":"tomcat.cxf.com","http":{"paths":[{"backend":{"serviceName":"tomcat-service","servicePort":80},"path":"/"}]}}]}}

Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  29s   nginx-ingress-controller  Ingress default/nginx-ingress

此时访问http://tomcat.cxf.com/ 就可以访问到tomcat了(需要使用域名)。文章来源地址https://www.toymoban.com/news/detail-535088.html

到了这里,关于Kubernetes(k8s)入门:核心组件详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【云原生 | Kubernetes 系列】K8s 实战 管理 Secret 详解

    Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 用户可以创建 Secret,同时系统也创建了一些 Secret。 一个 Secret 可以包含 Pod 访问数据库所需的用户凭证。 例如,由用户名和密码组成的数据库连接字符串。 你可

    2024年02月02日
    浏览(66)
  • 【云原生-K8s】Kubernetes安全组件CIS基准kube-beach安装及使用

    为了保证集群以及容器应用的安全,Kubernetes 提供了多种安全机制,限制容器的行为,减少容器和集群的攻击面,保证整个系统的安全性。 互联网安全中心(CIS,Center for Internet Security),是一个非盈利组织,致力为互联网提供免费的安全防御解决方案 官网 :https://www.cisecu

    2024年02月06日
    浏览(76)
  • 云原生Kubernetes:K8S概述

    目录 一、理论 1.云原生 2.K8S 3.k8s集群架构与组件 4.K8S网络 二、总结 (1)概念 云原生是一种基于容器、微服务和自动化运维的软件开发和部署方法。它可以使应用程序更加高效、可靠和可扩展,适用于各种不同的云平台。 如果要更直接通俗的来解释下上面的概念,云原生更

    2024年02月10日
    浏览(54)
  • Kubernetes技术--k8s核心技术 configMap

    1.概述    configMap最主要的作用是 存储一些 不加密 的数据 到 /etcd ,让pod以变量或者数据卷(volume)挂载到容器。    应用场景:配置文件、存储信息等 2.使用 -1. 创建配置文件。 这里我们需要先编写一个配置文件。使用redis,如下所示:

    2024年02月10日
    浏览(54)
  • Kubernetes技术--k8s核心技术 ingress

    1.引入        我们之前在部署应用(如nginx)的时候,如果你需要外部进行访问,使用的是service中的nodePort方式进行对外的暴露。然后外部就可以使用ip + 端口号来进行访问部署应用。         其实这一种方式是存在着较为明显的缺陷,每一个端口你只能够使用一次,一个端口

    2024年02月10日
    浏览(41)
  • Kubernetes技术--k8s核心技术Helm

    1.引入 我们先回顾一下之前部署 一个应用 的过程,如部署nginx,实现效果如下所示: -1.编写deployment的yaml文件,然后运行。 -2.使用service中的NodePort对外暴漏端口 -3.为了弥补Nodeport的缺陷,使用ingress实现转发        这样一个应用就部署完了,这一种情况相对于如果你需要部署

    2024年02月09日
    浏览(50)
  • Kubernetes技术--k8s核心技术 Secret

    1.概述      Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret可以以 Volume 或者环境变量的方式使用。 作用       加密数据存储在/etc中 ,使得 pod 容器以挂载volume方式进行访问 。在进行的数据存储中是以 base64

    2024年02月10日
    浏览(39)
  • 云原生Kubernetes:K8S存储卷

    目录 一、理论 1.存储卷 2.emptyDir 存储卷 3.hostPath卷 4.NFS共享存储 5.PVC 和 PV 6.静态创建PV 7.动态创建PV 二、实验  1.emptyDir 存储卷 2.hostPath卷 3.NFS共享存储 4.静态创建PV 5.动态创建PV 三、问题 1.生成pod一直pending 2.shoumount -e未显示共享目录 3.静态创建pv 报错 4.使用 Deployment 来创建

    2024年02月07日
    浏览(73)
  • 【云原生K8S】Kubernetes之探针

    目录 一、探针是什么 二、探针类型  Ⅰ、livenessProbe 容器重启策略  Ⅱ、readinessProbe Ⅲ、startupProbe 执行顺序: 字段详情 三、探测机制 Ⅰ、HTTP GET探针 Ⅱ、TCP套接字探针 Ⅲ、Exec探针 探针:是由 kubelet 对容器执行的定期诊断 要执行诊断,则需kubelet 调用由容器实现的 Handler。

    2024年02月09日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包