k8s-06-服务发现

掌握 SVC 原理及其构建方式
在这里插入图片描述
Pod、RC、Service关系

在这里插入图片描述
Service
Service定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实力。 Service与其后端Pod副本集群之间则是通过Label Selector来实现"无缝对接"。而RC的作用实际上是保证Service 的服务能力和服务质量处于预期的标准。
在这里插入图片描述
Service能够提供负载均衡能力,但是在使用上还有以下限制:
只提供4层负载,没有7层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的。
在这里插入图片描述
VIP和Service代理
在集群中,每个Node运行一个kube-proxy进程,kub-proxy负责为Service实现一种VIP(虚拟IP)的形式,而不是ExternalNmae的形式。
1.0版本,代理完全在userspace【kub-proxy压力较大】;
在这里插入图片描述
1.1版本,新增了iptables代理,单并不是默认运行模式,1.2起默认是iptables代理
在这里插入图片描述
1.8-beat.0添加了ipvs代理,1.14默认使用ipvs;【kube-proxy会监视kuberneters Service对象和EndPoints,调用netlink接口以相应地创建ipvs规则并定期与kuberneters Service对象和EndPoints 对象同步ipvs规则;以确保ipvs状态与期望一致,访问服务时,流量被重定向到其中一个后端pod与iptables类似,ipvs于netfilter的hook功能。但使用哈希表作为底层数据结构并在内核空间中工作,这意味着ipvs可以更快的重定向流量,并且在同步代理规则时具有更好的性能。此外ipvs为负载均衡算法提供了更多选项(rr-轮询/lc-最小连接数/dh-目标哈希/sh-源哈希/sed-最短期望值/nq-不排队调度)】
在这里插入图片描述

1)ipvs模式假定在运行kube-proxy之前在节点上都已经安装了ipvs内核模块,当kube-proxy以ipvs模式启动时,kube-proxy会验证节点上是否安装了ipvs模块,如果未安装kube-proxy将回退到iptables模式 # ipvsadm -Ln
2)1.0版本,Servie是4层;1.1中新增ingress API(bate),用来表示7层(HTTP)服务

kube-proxy开启ipvs的前置条件

  1. 安装IPvS
#  yum -y install ipvsadm ipset    # 默认安装(不用处理)

ipvs需要加载一些内核模块
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4

1.1)查看内核模块是否加载

lsmod|grep ip_vs
  1. 在各个节点执行以下脚本(如果没有加载,直接执行modprobe也行):
# cat > /etc/sysconfig/modules/ipvs.modules <<EOF
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
# chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
  1. kube-proxy开启ipvs并重启kube-proxy (master)
# kubectl edit configmap kube-proxy -n kube-system

找到如下部分的内容
  ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""  # scheduler默认是空,默认负载均衡算法为轮训
      strictARP: false
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
  kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: ""  # 其中mode原来是空,默认为iptables模式,改为ipvs
    nodePortAddresses: null
# kubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'
  1. 此时再像往常一样创建Deployment、Pod、Service之后查看就有ipvs规则了
# ipvsadm -Ln

四种类型 (pod和svc是多对多的关系)

为何不使用round-robin DNS? dns有缓存,很多服务都不会处理

一、ClusterIp:默认类型,自动分配一个Cluster内部可以访问的虚拟IP

1.创建deployment
# vim rs-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
        release: test
    spec:
      containers:
      - name: myapp
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

运行、查看
kubectl apply -f rs-deployment.yaml --record
kubectl get deployment
kubectl get pods

2.创建service 【 要和deployment 的标签一致 才能找到】
#vim server.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: test
  ports:
    - name: http
      port: 80
      targetPort: 80


运行、查看
kubectl apply -f server.yaml
kubectl get  service    # kubectl get  svc

3.测试访问

在这里插入图片描述
二、Headless Service (特殊的ClusterIp)有时不需要或不想要负载均衡,以及单独的Server IP.遇到这种情况,可以通过指定CluserIp 的值为"Node" 来创建Headless Service .这类Service并不会分配ClusterIp,kube-proxy不会处理他们,而且平台也不会为他们进行负载均衡和路由

# vim headless.yaml 

kind: Service
apiVersion: v1
metadata:
  name: headless-service
spec:
  selector:
    app: myapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  clusterIP: None
  
# kubectl apply -f headless.yaml
查询服务
# kubectl get svc
安装dig命令
# yum install bind-utils -y

查询DNS 【svc创建以后 会以域名的方式写入coredns】
# kubectl get pod -n kube-system -o wide          

A记录解析 无头服务名称.命名空间.集群地址. @DNS服务地址
# dig -t -A headless-service.default.svc.cluster.local. @10.244.0.34

实验结果(在无头服务中虽然没有自己的svc,但是可以通过访问域名的方式访问服务)
在这里插入图片描述
三、NodePort:在clusterip基础上为Service在每台机器上绑定一个端口,这样就可以用过NodePort来访问该服务

#vim node-port-server.yaml

apiVersion: v1
kind: Service
metadata:
  name: node-port-server
spec:
  type: NodePort
  selector:
    app: myapp
    release: test
  ports:
    - name: http
      port: 80
      targetPort: 80

测试访问:
在这里插入图片描述

通过访问 http://{nodeip}:31356 访问服务 所有的 node节点都会开启该端口

三+、LoadBalancer:在NodePort的基础上,借助cloud provider 创建一个外部负载均衡器,并将你请求转发到:NodePort (需要借助云供应商服务,需要收费)
在这里插入图片描述
四、ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任务类型代理被创建,这只有k8s 1.7或更高的kube-dns才支持

# vim baidu-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: baidu-service
spec:
  type: ExternalName
  externalName: www.baidu.com 
  
# kubectl apply -f baidu-service.yaml  
服务名称.命名空间.集群地址 访问外部服务
# dig -t A baidu-service.default.svc.cluster.local

Ingress

https://kubernetes.github.io/ingress-nginx/
https://github.com/kubernetes/ingress-nginx
在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,在Kubernetes 目前 提供了以下几种方案:
NodePort LoadBalancer Ingress
在这里插入图片描述
工作原理
1.ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,
2.然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,
3.再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,
4.然后reload一下使配置生效。以此达到域名分配置和动态更新的问题。

可以解决什么问题
1.动态配置服务
  如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作.
2.减少不必要的端口暴露
  配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式

组件:

configmap.yaml:提供configmap可以在线更行nginx的配置
default-backend.yaml:提供一个缺省的后台错误页面 404 namespace.yaml:创建一个独立的命名空间
ingress-nginx rbac.yaml:创建对应的role rolebinding 用于rbac
tcp-services-configmap.yaml:修改L4负载均衡配置的configmap
udp-services-configmap.yaml:修改L4负载均衡配置的configmap
with-rbac.yaml:有应用rbac的nginx-ingress-controller组件
service-nodeport:指定nginx的80端口和443端口

安装(不同版本安装方法差异比较大)

安装文件下载 :https://download.csdn.net/download/wenwang3000/14949569

下载安装文件

wget
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.43.0/deploy/static/provider/baremetal/deploy.yaml

Namespace

ingress-nginx

依赖的镜像 (注意版本)

docker.io/jettech/kube-webhook-certgen:v1.5.0
k8s.gcr.io/ingress-nginx/controller:v0.43.0  (该镜像下载不下来,需要替换成阿里云的)
#所有节点先安装镜像,镜像太大了 (记得修改配置文件中镜像地址)
docker pull docker.io/jettech/kube-webhook-certgen:v1.5.0
docker pull registry.aliyuncs.com/google_containers/nginx-ingress-controller:v0.43.0

无法直接在国内网络环境下从k8s.gcr.io下载镜像问题

阿里云代理仓库地址为:registry.aliyuncs.com/google_containers
比如下载
k8s.gcr.io/coredns:1.6.5
可以代理为:
registry.aliyuncs.com/google_containers/coredns:1.6.5

安装
 kubectl apply -f deploy.yaml
 验证 (Once the ingress controller pods are running, you can cancel the command typing Ctrl+C)
 kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --watch
 确认 ingress controller pods 是否启动
 [root@k8s ~]# kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-vtrc9        0/1     Completed   0          27m
ingress-nginx-admission-patch-8qn2l         0/1     Completed   0          27m
ingress-nginx-controller-6b6f79df87-8zrdv   1/1     Running     0          27m
查看版本号
[root@k8s svc]# kubectl exec -it ingress-nginx-controller-6b6f79df87-8zrdv -n ingress-nginx -- /nginx-ingress-controller --version
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       v0.43.0
  Build:         f3f6da12ac7c59b85ae7132f321bc3bcf144af04
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.19.6
查看服务
[root@k8s ~]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.100.172.233   <none>        80:31879/TCP,443:31041/TCP   29m
ingress-nginx-controller-admission   ClusterIP   10.102.21.102    <none>        443/TCP                      29m

可以通过 htpp(31879) https(31041)访问nginx服务

githubusercontent地址无法访问问题 https://zhuanlan.zhihu.com/p/107691233
#vim hosts
199.232.96.133 raw.githubusercontent.com

Ingress代理HTTP访问服务
(https://kubernetes.github.io/ingress-nginx/user-guide/basic-usage/)
deployment+service

# vim myapp-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
        release: test
    spec:
      containers:
      - name: myapp
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: test
  ports:
    - name: http
      port: 80
      targetPort: 80
# kubectl apply -f  myapp-svc.yaml
# kubectl get pods
# kubectl get svc     

创建对应的一个ingress对象来暴露集群里这个 deployment 的 http 服务

# vim ingress-myapp.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp-v1
  annotations:
    # use the shared ingress-nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: test.ingress.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-service
          servicePort: 80
# kubectl apply -f  ingress-myapp.yaml
域名解析
192.168.44.129 test.ingress.com 
访问 (注意端口是ingress暴漏的http端口)服务
http://test.ingress.com:31879
查看
# kubectl get ingress

Ingress代理HTTPS访问服务
https://kubernetes.github.io/ingress-nginx/user-guide/tls/
创建证书

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=test.ingress.com/O=test.ingress.com"

kubectl create secret tls tls-secret --key tls.key --cert tls.crt

部署ingress

# vim ingress-https-myapp.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp-v1
  annotations:
    # use the shared ingress-nginx
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: test.ingress.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-service
          servicePort: 80
# kubectl apply -f  ingress-https-myapp.yaml
域名解析
192.168.44.129 test.ingress.com 
访问 (注意端口是ingress暴漏的https端口)服务
https://test.ingress.com:31041/
查看
# kubectl get ingress

Nginx进行BasicAuth
(https://kubernetes.github.io/ingress-nginx/examples/auth/basic/)

安装依赖
yum -y install httpd
创建密码文件 (用户名/密码:foo/123456)
[root@k8s basic-auth]# htpasswd -c auth foo
New password: 
Re-type new password: 
Adding password for user foo
保存密码文件
kubectl create secret generic basic-auth --from-file=auth

部署ingress

# vim ingress-basic.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-with-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
  rules:
  - host: test.ingress.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-service
          servicePort: 80
域名解析
192.168.44.129 test.ingress.com 
访问 (注意端口是ingress暴漏的http端口)服务
http://test.ingress.com:31879
查看
# kubectl get ingress     

在这里插入图片描述
Nginx进行重写
(https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target)

nginx.ingress.kubernetes.io/rewrite-target 必须重定向流量的目标URI string
nginx.ingress.kubernetes.io/ssl-redirect
指示位置部分是否仅可以访问ssl(当ingress包含证书时默认为true) bool
nginx.ingress.kubernetes.io/force-ssl-redirect
j即使ingress未启用TLS,也强制定向到https bool nginx.ingress.kubernetes.io/app-root
定义Controller必须重定向的应用程序,如果它在’/上下文中’ string
nginx.ingress.kubernetes.io/use-regex 指示ingress上定义的路径是否使用正则表达式 bool

# vim ingress-rewrite.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: http://test.ingress.com:31879
  name: rewrite
  namespace: default
spec:
  rules:
  - host: k8s.master.com
    http:
      paths:
      - path: /
        backend:
          serviceName: http-svc
          servicePort: 80
域名解析
192.168.44.129 k8s.master.com
192.168.44.129 test.ingress.com
访问 (注意端口是ingress暴漏的http端口)服务
 http://k8s.master.com:31879/
 重定向到
 http://test.ingress.com:31879
查看
# kubectl get ingress            

猜你喜欢

转载自blog.csdn.net/wenwang3000/article/details/113335589