Kubernetes(7) Ingress

Service has only 4 Layers (iptables, ipvs have 4 layers), which means, it can only work on TCP/IP Layer or the 4. Layer of ISO/OSI Model. If client need to send application a https request, where should we put the SSL certificate for https?

The answer is Ingress Controller, for this there are three options:

  • Nginx
  • Traefik
  • Envoy

How Ingress works:

1 Install Ingress Controller

for installation see at: https://github.com/kubernetes/ingress-nginx/tree/master/deploy

for file in namespace.yaml configmap.yaml rbac.yaml with-rbac.yaml mandatory.yaml; do wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/$file; done

First of all we need a new namespace for Ingress-Controller:

kubectl apply -f namespace.yaml

This commnd will create a new namespace with name ingress-nginx

Then the rest services:

[root@k8smaster ingress-nginx]# kubectl apply -f .

configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
namespace/ingress-nginx unchanged
configmap/nginx-configuration unchanged
configmap/tcp-services unchanged
configmap/udp-services unchanged
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
namespace/ingress-nginx unchanged
serviceaccount/nginx-ingress-serviceaccount unchanged
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole unchanged
role.rbac.authorization.k8s.io/nginx-ingress-role unchanged
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding unchanged
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding unchanged
deployment.apps/nginx-ingress-controller unchanged

[root@k8smaster ingress-nginx]# kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-6f84777694-59xpv   1/1     Running   0          1m

We want to use Ingress to provide service also to external client. In order to do this, we need one more Service - NodePort (Installation reference also see: https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal)

In this example it doesn't mention on which port this service should exposed. We will define it by ourself:

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

As you see nodePort: 30080 and 30443 are new defined by us! Then deploy this service

root@k8smaster ingress-nginx]# kubectl apply -f service-nodeport.yaml
service/ingress-nginx created

[root@k8smaster ingress
-nginx]# kubectl get svc -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.103.72.25 <none> 80:30080/TCP,443:30443/TCP 16s

Now we have a Ingress controller up and running.

2. Perform a handson with Ingress

For this Handson I'm gonna to create a deployment with 3 replicas and a Service, which forward service 80 to container port 80. After this I create a new Ingress-Service and assign it to Service myapp-svc. With Host myapp.crazy-chinese.com I can access the myapp-svc and finnaly reach the backend pods (deployment myapp-deployment).

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-myapp
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: myapp.crazy-chinese.com
      http:
        paths:
          - backend:
              serviceName: myapp-svc
              servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  ports:
    - name: http
      port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
        - name: myapp-container
          image: ikubernetes/myapp:v1
          ports:
            - name: http
              containerPort: 80

Then apply the template you can see:

[root@k8smaster ingress]# kubectl get pods -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP            NODE
myapp-deployment-f5f97bb54-2mpqg   1/1     Running   0          15m   10.244.1.66   k8snode1
myapp-deployment-f5f97bb54-gjmz7   1/1     Running   0          15m   10.244.2.50   k8snode2
myapp-deployment-f5f97bb54-zjz6r   1/1     Running   0          15m   10.244.1.65   k8snode1

[root@k8smaster ingress]# kubectl get svc
-o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24d <none> myapp-svc ClusterIP 10.98.111.57 <none> 80/TCP 15m app=myapp,release=canary [root@k8smaster ingress]# kubectl get ingress NAME HOSTS ADDRESS PORTS AGE ingress-myapp myapp.crazy-chinese.com 80 15m

Because of host myapp.crazy-chinese.com is still unknow on my client machine. I must add this to my /etc/hosts file.

127.0.0.1       localhost
127.0.1.1       bai

172.16.0.11 k8smaster
172.16.0.12 k8snode1 myapp.crazy-chinese.com
172.16.0.13 k8snode2 myapp.crazy-chinese.com

Now I open my web browser and tipp http://myapp.crazy-chinese.com:30080

it shows me, that I can reach my application backend!

3 Create Certificat for HTTPS

We want create and sign a certificat for https request:

[root@k8smaster ingress]# openssl genrsa -out tls.key 2048
Generating RSA private key, 2048 bit long modulus
..........+++
....+++
e is 65537 (0x10001)

[root@k8smaster ingress]# openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Munich/L=Munich/O=DevOps/CN=tomcat.crazy-chinese.com
[root@k8smaster ingress]# ll
total 16-rw-r--r-- 1 root root 1310 Jan 27 07:17 tls.crt
-rw-r--r-- 1 root root 1679 Jan 27 07:16 tls.key
[root@k8smaster ingress]# kubectl create secret tls tomcat
-ingress-secret --cert=tls.crt --key=tls.key secret/tomcat-ingress-secret created

[root@k8smaster ingress]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
default-token-rxs5t     kubernetes.io/service-account-token   3      24d
tomcat-ingress-secret   kubernetes.io/tls                     2      1m


[root@k8smaster ingress]# kubectl describe secret tomcat-ingress-secret
Name:         tomcat-ingress-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1310 bytes
tls.key:  1679 bytes

Add following template to create deployment, service and ingress for tomcat application and enable tls certificate:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tomcat-tls
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
    - hosts:
        - tomcat.crazy-chinese.com
    - secretName: tomcat-ingress-secret
  rules:
    - host: tomcat.crazy-chinese.com
      http:
        paths:
          - backend:
              serviceName: tomcat-svc
              servicePort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-svc
  namespace: default
spec:
  selector:
    app: tomcat
    release: canary
  ports:
    - name: http
      port: 8080
      targetPort: 8080
    - name: ajp
      port: 8009
      targetPort: 8009
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-deployment
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat
      release: canary
  template:
    metadata:
      labels:
        app: tomcat
        release: canary
    spec:
      containers:
        - name: tomcat-container
          image: tomcat:8.5.32-jre8-alpine
          ports:
            - name: http
              containerPort: 8080
            - name: ajp
              containerPort: 8009

We see in host option, we specified tomcat.crazy-chinese.com als url, which should be encripted by using spec.tls.hosts

With spec.tls.secretname we can specifiy the name of tls certificate.

After this create the service, we can use https://tomcat.crazy-chinese.com:30443/ to visit tomcat default page...

猜你喜欢

转载自www.cnblogs.com/crazy-chinese/p/10401660.html