【容器应用系列教程】Kubernetes服务管理Service

一、关于Service

  • 业务的访问入口
  • 负载均衡功能
  • 服务名称
    • 命名格式:服务名称.命名空间.svc.cluster.local
    • 例子:wordpress.default.svc.cluster.local
  • 依赖于coreDNS组件
    • 服务发现
      • 创建服务时,会自动在coreDNS中注册名称、IP的解析关系
      • 创建pod时,pod会自动使用DNS解析对应的服务名称
  • Service服务、POD依赖于标签选择器建立对应关系

kubernetes06

查看刚创建Kubernetes自带的2个默认的Service

svcservice的简写

[root@k8s-master opt]# kubectl get svc -n default
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.16.0.1   <none>        443/TCP   4d3h
[root@k8s-master opt]# kubectl get svc -n kube-system
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   172.16.0.10   <none>        53/UDP,53/TCP,9153/TCP   4d3h

二、Service的类型

  • ClusterIP
    • 仅在集群内部可以被访问
  • NodePort
    • 将服务发布到物理机
  • LoadBalance
    • 适用于公有云场景

三、ClusterIP类型

  • clusterIP的服务
    • 集群内部服务A访问服务B时,DNS组件会将其解析到服务B对应的IP
  • clusterIP的服务
    • 集群内部服务A访问服务B时,由于服务B没有IPDNS会直接解析到对应的Pod地址上
    • 缺点
      • 由于直接解析到Pod上,失去了kube-proxy提供的负载均衡,在该Pod宕机时,会导致服务无法正常访问

1.创建一个有ClusterIP的服务

[root@k8s-master wordpress]# vim nginx.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx
    namespace: wordpress
spec:
    replicas: 2
    selector:
        matchLabels:
            app: nginx
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 1
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
            - name: nginx
              image: nginx:latest
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
---	#创建不同的服务,可以使用分隔符隔开
apiVersion: v1
kind: Service
metadata:
    name: nginx
    namespace: wordpress
spec:
    ports:
    - port: 80
    selector:
      app: nginx
[root@k8s-master wordpress]# kubectl create -f ./nginx.yml

deployment.apps/nginx created
service/nginx created

查看servivePod

[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   172.16.14.75   <none>        80/TCP    16s
[root@k8s-master wordpress]# kubectl get pods -n wordpress -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
nginx-75b69bd684-2dwkk   1/1     Running   0          2m40s   192.168.242.153   k8s-node02.linux.com   <none>           <none>
nginx-75b69bd684-8fp7t   1/1     Running   0          2m40s   192.168.201.216   k8s-node01.linux.com   <none>           <none>

创建测试容器

clusterIP模式的service只能集群内部进行访问

[root@k8s-master wordpress]# vim centos.yml

apiVersion: v1
kind: Pod
metadata:
    name: centos
    namespace: wordpress
spec:
    containers:
    - name: centos
      image: centos:7
      imagePullPolicy: IfNotPresent
      tty: true
      resources:
            requests:
                memory: "1G"
                cpu: "500m"
            limits:
                memory: "2G"
                cpu: "1"
[root@k8s-master wordpress]# kubectl create -f centos.yml

pod/centos created

访问测试

注意,短域名只能在同namespace下适用,如果servicepod不在同一个namesapce那么只能使用全域名访问

[root@k8s-master wordpress]# kubectl exec -it centos -n wordpress -- bash

[root@centos /]# curl nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

[root@centos /]# curl nginx.wordpress.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

2.创建一个无clusterIP的服务

[root@k8s-master wordpress]# vim nginx.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx
    namespace: wordpress
spec:
    replicas: 2
    selector:
        matchLabels:
            app: nginx
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 1
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
            - name: nginx
              image: nginx:latest
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
    name: nginx
    namespace: wordpress
spec:
    clusterIP: None	#指定无IP
    ports:
    - port: 80
    selector:
      app: nginx
[root@k8s-master wordpress]# kubectl create -f nginx.yml 
deployment.apps/nginx created

查看servicePod

[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    79s
[root@k8s-master wordpress]# kubectl get pod -n wordpress -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
centos                   1/1     Running   0          12m     192.168.242.154   k8s-node02.linux.com   <none>           <none>
nginx-75b69bd684-gdp9b   1/1     Running   0          3m55s   192.168.201.217   k8s-node01.linux.com   <none>           <none>
nginx-75b69bd684-htvbh   1/1     Running   0          3m55s   192.168.201.218   k8s-node01.linux.com   <none>           <none>

测试访问

可以看到DNS解析的IPPod上面的IP

[root@k8s-master wordpress]# kubectl exec -it centos -n wordpress -- bash

[root@centos /]# ping nginx.wordpress.svc.cluster.local
PING nginx.wordpress.svc.cluster.local (192.168.201.217) 56(84) bytes of data.
64 bytes from 192-168-201-217.nginx.wordpress.svc.cluster.local (192.168.201.217): icmp_seq=1 ttl=62 time=0.231 ms
64 bytes from 192-168-201-217.nginx.wordpress.svc.cluster.local (192.168.201.217): icmp_seq=2 ttl=62 time=0.238 ms

[root@centos /]# curl nginx.wordpress.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

四、NodePort类型

该类型的服务会将服务端口暴露在物理机上,可以借助物理机直接访问

1.创建NodePort

[root@k8s-master wordpress]# vim nginx.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx
    namespace: wordpress
spec:
    replicas: 2
    selector:
        matchLabels:
            app: nginx
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 1
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
            - name: nginx
              image: nginx:latest
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
    name: nginx
    namespace: wordpress
spec:
    type: NodePort	#类型NodePort
    ports:
    - port: 80
      nodePort: 30002	#端口范围在30000-32767
    selector:
      app: nginx
[root@k8s-master wordpress]# kubectl create -f nginx.yml

deployment.apps/nginx created
service/nginx created

查看Pod运行在哪个node

[root@k8s-master wordpress]# kubectl get pods -n wordpress -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
nginx-75b69bd684-jls9n   1/1     Running   0          2m30s   192.168.201.219   k8s-node01.linux.com   <none>           <none>
nginx-75b69bd684-lphpv   1/1     Running   0          2m30s   192.168.242.155   k8s-node02.linux.com   <none>           <none>

查看Service

[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   172.16.125.146   <none>        80:30002/TCP   3m19s

物理机访问测试

这里填写是物理机的IP

kubernetes07

kubernetes08

2.实验

使用Kubernetes部署Wordpress

创建命名空间

[root@k8s-master wordpress]# kubectl create ns wordpress

编写数据库yml

[root@k8s-master wordpress]# vim wp-mysql.yml

apiVersion: apps/v1
kind: Deployment	#类型
metadata:
    name: wp-mysql
    namespace: wordpress	#加入到wordpress命名空间
spec:
    replicas: 1	#1个副本集
    selector:
        matchLabels:
            app: wp-mysql	#此处标签应该和下面你的容器标签对应
    strategy:	#滚动更新策略
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
    template:	#容器的标签
        metadata:
            labels:
                app: wp-mysql
        spec:
            containers:
            - name: wp-mysql
              image: mysql:5.7
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 3306
              env:	#传递变量
              - name: MYSQL_ROOT_PASSWORD
                value: "WWW.1.com"	#设置root用户密码
              resources:	#资源限制
                requests:
                  memory: "1G"
                  cpu: "1"
                limits:
                  memory: "2G"
                  cpu: "2"
---
apiVersion: v1
kind: Service
metadata:
    name: wp-mysql
    namespace: wordpress	#加入到wordpress命名标签
spec:
    ports:
    - port: 3306
    selector:
      app: wp-mysql	#此处标签对应上面容器的标签
[root@k8s-master wordpress]# kubectl create -f wp-mysql.yml

[root@k8s-master wordpress]# kubectl get pod -n wordpress
NAME                       READY   STATUS    RESTARTS   AGE
wp-mysql-cbcd75979-2dxkm   1/1     Running   0          3m36s

[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
wp-mysql   ClusterIP   172.16.166.18   <none>        3306/TCP   4m9s

创建wordpress用到的库和用户

[root@k8s-master wordpress]# kubectl exec -it wp-mysql-cbcd75979-2dxkm -n wordpress -- bash

bash-4.2# mysql -uroot -pWWW.1.com
mysql> create database wordpress charset utf8mb4;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on wordpress.* to 'wordpress'@'%' identified by 'WWW.1.com';
Query OK, 0 rows affected, 1 warning (0.00 sec)

编辑wordpressyml文件

[root@k8s-master wordpress]# vim wordpress.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: wordpress
    namespace: wordpress
spec:
    replicas: 1
    selector:
        matchLabels:
            app: wordpress
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
    template:
        metadata:
            labels:
                app: wordpress
        spec:
            containers:
            - name: wordpress
              image: wordpress
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
              env:
              - name: WORDPRESS_DB_HOST
                value: wp-mysql	#此处数据库地址为cronDNS解析地址,也可以是全名,wp-mysql.wordpress.svc.cluster.local
              - name: WORDPRESS_DB_USER
                value: wordpress  
              - name: WORDPRESS_DB_PASSWORD
                value: WWW.1.com
              - name: WORDPRESS_DB_NAME
                value: wordpress 
              - name: WORDPRESS_TABLE_PREFIX
                value: wp_
              resources:
                requests:
                  memory: "1G"
                  cpu: "1"
                limits:
                  memory: "2G"
                  cpu: "2"
---
apiVersion: v1
kind: Service
metadata:
    name: wordpress
    namespace: wordpress
spec:
    type: NodePort
    ports:
    - port: 80
      nodePort: 30005
    selector:
      app: wordpress
[root@k8s-master wordpress]# kubectl create -f wordpress.yml
[root@k8s-master wordpress]# kubectl get pod -n wordpress -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
wordpress-657f59cdf5-82f7v   1/1     Running   0          2m42s   192.168.201.221   k8s-node01.linux.com   <none>           <none>
wp-mysql-cbcd75979-2dxkm     1/1     Running   0          16m     192.168.242.156   k8s-node02.linux.com   <none>           <none>

[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
wordpress   NodePort    172.16.200.34   <none>        3306:30005/TCP   2m16s
wp-mysql    ClusterIP   172.16.166.18   <none>        3306/TCP         16m

访问测试

kubernetes09

后面安装配置过程省略

五、Ingress发布服务

1.关于Ingress

  • 之前在k8s集群内部对外暴露服务的方式用的是nodePort,但采用NodePort方式暴露服务面临问题是,服务一旦多起来,NodePort在每个节点上开启的端口会及其庞大,而且难以维护
  • 因此,后续出现了一种新的方式,称为ingressingress类似于coreDNS是作为k8s的插件存在的,借助ingress一样可对外暴露服务
  • 基于ingress暴露服务时,类似于七层调度,对外可提供一个主机名,将不同的服务以不同的端口方式映射到该主机名上,客户端直接通过主机名进行访问

2.Ingress核心组件

  • ingress
    • 一种资源对象,用于描述服务规则
  • ingress-controller
    • Ingress Controller通过与Kubernetes API交互,动态的去感知集群中Ingress规则变化,然后读取他,按照他自己模板生成一段Nginx配置,再写到Nginx Pod里,最后reload一下

3.Ingress服务名访问实现方式

  • nginx
  • haproxy
  • traefik

4.Ingress-nginx部署

A.准备Ingress-nginxyaml文件

可以前往Github仓库地址下载想要的版本:https://github.com/kubernetes/ingress-nginx
或者使用我这里准备好的yaml文件:https://pan.baidu.com/s/1l9cF-AShYicLk1arwVboEw?pwd=jge3
由于本人使用的kubernetes版本是1.20.7所以使用ingress-nginx_v1.3.1版本

B.修改igress-nginx.yml文件

如果使用的是我提供的yml文件,可以不做修改

#添加配置Pod网络模式为host
416行 hostNetwork: true
#修改镜像下载地址为国内地址
439行 image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.3.1
536行 image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.3.0
585行 image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v1.3.0

C、部署Ingress-nginx_v1.3.1

[root@k8s-master wordpress]# kubectl create -f ./ingress-nginx-deploy_v1.3.1.yaml
[root@k8s-master wordpress]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-h2mpq        0/1     Completed   0          153m
ingress-nginx-admission-patch-2v2vc         0/1     Completed   1          153m
ingress-nginx-controller-64ff7cd7cf-58qkl   1/1     Running     0          153m

[root@k8s-master wordpress]# kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   172.16.100.79   <pending>     80:32754/TCP,443:31928/TCP   153m
ingress-nginx-controller-admission   ClusterIP      172.16.18.128   <none>        443/TCP                      153m

D.准备Pod

[root@k8s-master wordpress]# vim nginx.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx
    namespace: wordpress
spec:
    replicas: 2
    selector:
        matchLabels:
            app: nginx
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 1
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
            - name: nginx
              image: nginx:latest
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
    name: nginx
    namespace: wordpress
spec:	#创建一个clusterIP类型
    ports:
    - port: 80
    selector:
      app: nginx
[root@k8s-master wordpress]# kubectl create -f nginx.yml 
deployment.apps/nginx created
service/nginx created

E.准备ingress

[root@k8s-master wordpress]# vim ingress.yml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-wp
  namespace: wordpress	#命名空间
  annotations:	#注释说明信息
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: ng.linux.com
    http:
      paths:
      - path:
        backend:
          serviceName: nginx	#对应的svc服务名
          servicePort: 80	#svc服务对应的端口
[root@k8s-master wordpress]# kubectl create -f ingress.yml

Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/ingress-wp created

F.访问测试

查看ingress
[root@k8s-master wordpress]# kubectl get ingress -n wordpress
NAME         CLASS    HOSTS          ADDRESS   PORTS   AGE
ingress-wp   <none>   ng.linux.com             80      54s
查看controller跑在哪个物理机上

我这里跑在node1
controller运行在哪个服务器上,决定我们的解析地址在哪里

[root@k8s-master wordpress]# kubectl get pods -n ingress-nginx -o wide
NAME                                        READY   STATUS      RESTARTS   AGE    IP                NODE                   NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-h2mpq        0/1     Completed   0          172m   192.168.242.159   k8s-node02.linux.com   <none>           <none>
ingress-nginx-admission-patch-2v2vc         0/1     Completed   1          172m   192.168.201.225   k8s-node01.linux.com   <none>           <none>
ingress-nginx-controller-64ff7cd7cf-58qkl   1/1     Running     0          172m   192.168.140.11    k8s-node01.linux.com   <none>           <none>
配置域名解析

路径:C:\Windows\System32\drivers\etc\hosts

kubernetes10

访问测试

kubernetes11

5.实验:使用Ingress-nginx发布wordpress

A.创建命名空间

[root@k8s-master wordpress]# kubectl create ns wordpress

B.创建Mysql容器

[root@k8s-master wordpress]# vim wp-mysql.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: wp-mysql
    namespace: wordpress
spec:
    replicas: 1
    selector:
        matchLabels:
            app: wp-mysql
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
    template:
        metadata:
            labels:
                app: wp-mysql
        spec:
            containers:
            - name: wp-mysql
              image: mysql:5.7
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 3306
              env:
              - name: MYSQL_ROOT_PASSWORD
                value: "WWW.1.com"
              resources:
                requests:
                  memory: "1G"
                  cpu: "1"
                limits:
                  memory: "2G"
                  cpu: "2"
---
apiVersion: v1
kind: Service
metadata:
    name: wp-mysql
    namespace: wordpress
spec:
    ports:
    - port: 3306
    selector:
      app: wp-mysql
[root@k8s-master wordpress]# kubectl create -f wp-mysql.yml 
deployment.apps/wp-mysql created
service/wp-mysql created

C.创建wordpress用到的库和用户

[root@k8s-master wordpress]# kubectl -it exec wp-mysql-cbcd75979-tfk9r -n wordpress -- bash
bash-4.2# mysql -uroot -pWWW.1.com
mysql> create database wordpress charset utf8mb4;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on wordpress.* to 'wordpress'@'%' identified by 'redhat';
Query OK, 0 rows affected, 1 warning (0.00 sec)

D.创建Wordpress容器

[root@k8s-master wordpress]# vim wordpress.yml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: wordpress
    namespace: wordpress
spec:
    replicas: 1
    selector:
        matchLabels:
            app: wordpress
    strategy:
        type: RollingUpdate
        rollingUpdate:
            maxSurge: 1
            maxUnavailable: 0
    template:
        metadata:
            labels:
                app: wordpress
        spec:
            containers:
            - name: wordpress
              image: wordpress
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
              env:
              - name: WORDPRESS_DB_HOST
                value: wp-mysql
              - name: WORDPRESS_DB_USER
                value: wordpress  
              - name: WORDPRESS_DB_PASSWORD
                value: redhat
              - name: WORDPRESS_DB_NAME
                value: wordpress 
              - name: WORDPRESS_TABLE_PREFIX
                value: wp_
              resources:
                requests:
                  memory: "1G"
                  cpu: "1"
                limits:
                  memory: "2G"
                  cpu: "2"
---
apiVersion: v1
kind: Service
metadata:
    name: wordpress
    namespace: wordpress
spec:	#注意服务类型为clusterIP
    ports:
    - port: 80
    selector:
      app: wordpress
[root@k8s-master wordpress]# kubectl create -f wordpress.yml 
deployment.apps/wordpress created
service/wordpress created
查看服务
[root@k8s-master wordpress]# kubectl get svc -n wordpress
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
wordpress   ClusterIP   172.16.67.252   <none>        80/TCP     88s
wp-mysql    ClusterIP   172.16.192.50   <none>        3306/TCP   9m23s

E.创建Ingress服务

[root@k8s-master wordpress]# vim ingress.yml

apiVersion: extensions/v1beta1
kind: Ingress 
metadata:
  name: ingress-wp
  namespace: wordpress	#指定命名空间
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules: 
  - host: wp.linux.com	#自定义访问域名
    http:
      paths: 
      - path:  
        backend: 
          serviceName: wordpress	#此处服务名,应该对应wordpress的服务名字
          servicePort: 80
[root@k8s-master wordpress]# kubectl create -f ingress.yml 
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/ingress-wp created
查看Ingress
[root@k8s-master wordpress]# kubectl get ingress -n wordpress
NAME         CLASS    HOSTS          ADDRESS   PORTS   AGE
ingress-wp   <none>   wp.linux.com             80      46s
查看controller容器在哪台实体机上

controller跑在哪台机器上,决定我们解析地址在哪里

[root@k8s-master wordpress]# kubectl get pod -n ingress-nginx -o wide
NAME                                        READY   STATUS      RESTARTS   AGE   IP                NODE                   NOMINATED NODE   READINESS GATES
ingress-nginx-admission-create-h2mpq        0/1     Completed   0          10h   192.168.242.159   k8s-node02.linux.com   <none>           <none>
ingress-nginx-admission-patch-2v2vc         0/1     Completed   1          10h   192.168.201.225   k8s-node01.linux.com   <none>           <none>
ingress-nginx-controller-64ff7cd7cf-58qkl   1/1     Running     0          10h   192.168.140.11    k8s-node01.linux.com   <none>           <none>

F.修改host文件

路径:C:\Windows\System32\drivers\etc\hosts

kubernetes12

G.浏览器访问测试

kubernetes13