Chủ Nhật, 22 tháng 12, 2019

Sử dụng Service và Secret Tls trong Kubernetes

Service trong Kubernetes


Các POD được quản lý trong Kubernetes, trong vòng đời của nó chỉ diễn ra theo hướng - được tạo ra, chạy và khi nó kết thúc thì bị xóa và khởi tạo POD mới thay thế. ! Có nghĩa ta không thể có tạm dừng POD, chạy lại POD đang dừng ...
Mặc dù mỗi POD khi tạo ra nó có một IP để liên lạc, tuy nhiên vấn đề là mỗi khi POD thay thế thì là một IP khác, nên các dịch vụ truy cập không biết IP mới nếu ta cấu hình nó truy cập đến POD nào đó cố định. Để giải quết vấn đề này sẽ cần đến Service.
Service (micro-service) là một đối tượng trừu tượng nó xác định ra một nhóm các POD và chính sách để truy cập đến POD đó. Nhóm cá POD mà Service xác định thường dùng kỹ thuật Selector (chọn các POD thuộc về Service theo label của POD).
Cũng có thể hiểu Service là một dịch vụ mạng, tạo cơ chế cân bằng tải (load balancing) truy cập đến các điểm cuối (thường là các Pod) mà Service đó phục vụ.
kubernetes

Tạo Service Kubernetes

Tham khảo API để viết cấu hình manifest yaml: Service V1 Core

Tạo Service kiểu ClusterIP, không Selector

1.svc1.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc1
spec:
  type: ClusterIP
  ports:
    - name: port1
      port: 80
      targetPort: 80
File trên khai báo một service đặt tên svc1, kiểu của service là ClusterIP, đây là kiểu mặc định (ngoài ra còn có kiểu NodePort, LoadBalancer, ExternalName), phần khai báo cổng gồm có cổng của service (port) tương ứng ánh xạ vào cổng của endpoint (targetPort - thường là cổng Pod).
Triển khai file trên
kubectl apply -f 1.svc1.yaml

# lấy các service
kubectl get svc -o wide

# xem thông tin của service svc1
kubectl describe svc/svc1
kubernetes
Hệ thống đã tạo ra service có tên là svc1 với địa chỉ IP là 10.97.217.42, khi Pod truy cập địa chỉ IP này với cổng 80 thì nó truy cập đến các endpoint định nghĩa trong dịch vụ. Tuy nhiên thông tin service cho biết phần endpoints là không có gì, có nghĩa là truy cập thì không có phản hồi nào.

Tạo EndPoint cho Service (không selector)

Service trên có tên svc1, không có selector để xác định các Pod là endpoint của nó, nên có thể tự tạo ra một endpoint cùng tên svc1
2.endpoint
apiVersion: v1
kind: Endpoints
metadata:
  name: svc1
subsets:
  - addresses:
      - ip: 216.58.220.195      # đây là IP google
    ports:
      - name: port1
        port: 80
Triển khai với lệnh
kubectl apply -f 2.endpoint.yaml
Xem lại thông tin
kubectl describe svc/svc1

Name:              svc1
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration: ...
Selector:          <none>
Type:              ClusterIP
IP:                10.97.217.42
Port:              port1  80/TCP
TargetPort:        80/TCP
Endpoints:         216.58.220.195:80
Session Affinity:  None
Events:            <none>
Như vậy svc1 đã có endpoints, khi truy cập svc1:80 hoặc svc1.default:80 hoặc 10.97.217.42:80 có nghĩa là truy cập 216.58.220.195:80
Do có dịch vụ CoreDns nên có thể truy cập thông qua phân giải tên, truy cập đến service theo cấu trúc namespace.servicename nếu cùng namespace chỉ cần servicenname
Ví dụ trên sử dụng Service (không có Selector), cần tạo Endpoint có tên cùng tên Service: dùng loại này khi cần tạo ra một điểm truy cập dịch vụ tương tự như proxy đến một địa chỉ khác (một server khác, một dịch vụ khác ở namespace khác ...)

Thực hành tạo Service có Selector, chọn các Pod là Endpoint của Service

Trước tiên triển khai trên Cluster 2 POD chạy độc lập, các POD đó đều có nhãn app: app1
3.pods.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp1
  labels:
    app: app1
spec:
  containers:
  - name: n1
    image: nginx
    resources:
      limits:
        memory: "128Mi"
        cpu: "100m"
    ports:
      - containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp2
  labels:
    app: app1
spec:
  containers:
  - name: n1
    image: httpd
    resources:
      limits:
        memory: "128Mi"
        cpu: "100m"
    ports:
      - containerPort: 80
Triển khai file trên
kubectl apply -f 3.pods.yaml
kubernetes
Nó tạo ra 2 POD myapp1 (192.168.41.147 chạy nginx) và myapp2 (192.168.182.11 chạy httpd), chúng đều có nhãn app=app1
Tiếp tục tạo ra service có tên svc2 có thêm thiết lập selector chọn nhãn app=app1
4.svc2.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc2
spec:
  selector:
     app: app1
  type: ClusterIP
  ports:
    - name: port1
      port: 80
      targetPort: 80
Triển khai và kiểm tra
$ 04-svc $ kubectl apply -f 4.svc2.yaml
service/svc2 created

$ 04-svc $ kubectl describe svc/svc2
Name:              svc2
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration: ...
Selector:          app=app1
Type:              ClusterIP
IP:                10.100.165.105
Port:              port1  80/TCP
TargetPort:        80/TCP
Endpoints:         192.168.182.11:80,192.168.41.147:80
Session Affinity:  None
Events:            <none>
Thông tin trên ta có, endpoint của svc2192.168.182.11:80,192.168.41.147:80, hai IP này tương ứng là của 2 POD trên. Khi truy cập địa chỉ svc2:80 hoặc 10.100.165.105:80 thì căn bằng tải hoạt động sẽ là truy cập đến 192.168.182.11:80 (myapp1) hoặc 192.168.41.147:80 (myapp2)

Thực hành tạo Service kiểu NodePort

Kiểu NodePort này tạo ra có thể truy cập từ ngoài internet bằng IP của các Node, ví dụ sửa dịch vụ svc2 trên thành dịch vụ svc3 kiểu NodePort
5.svc3.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc3
spec:
  selector:
     app: app1
  type: NodePort
  ports:
    - name: port1
      port: 80
      targetPort: 80
      nodePort: 31080
Trong file trên, thiết lập kiểu với type: NodePort, lúc này Service tạo ra có thể truy cập từ các IP của Node với một cổng nó ngẫu nhiên sinh ra trong khoảng 30000-32767. Nếu muốn ấn định một cổng của Service mà không để ngẫu nhiên thì dùng tham số nodePort như trên.
Triển khai file trên
kubectl appy -f 5.svc3.yaml
Sau khi triển khai có thể truy cập với IP là địa chỉ IP của các Node và cổng là 31080, ví dụ 172.16.10.101:31080

Ví dụ ứng dụng Service, Deployment, Secret

Trong ví dụ này, sẽ thực hành triển khai chạy máy chủ nginx với mức độ áp dụng phức tạp hơn đó là:
  • Xây dựng một image mới từ image cơ sở nginx rồi đưa lên registry Hub Docker đặt tên là ichte/swarmtest:nginx
  • Tạo Secret chứa xác thực SSL sử dụng bởi ichte/swarmtest:nginx
  • Tạo deployment chạy/quản lý các POD có chạy ichte/swarmtest:nginx
  • Tạo Service kiểu NodePort để truy cập đến các POD trên

Xây dựng image ichte/swarmtest:nginx

Image cơ sở là nginx (chọn tag bản 1.17.6), đây là một proxy nhận các yêu cầu gửi đến. Ta sẽ cấu hình để nó nhận các yêu cầu http (cổng 80) và https (cổng 443).
Tạo ra thư mục nginx để chứa các file dữ liệu, đầu tiên là tạo ra file cấu hình nginx.conf, file cấu hình này được copy vào image ở đường dẫn /etc/nginx/nginx.conf khi build image.
1) Chuẩn bị file cấu hình nginx.conf
nginx.conf
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
  worker_connections  4096;  ## Default: 1024
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;
    #gzip  on;
    server {
        listen 80;
        server_name localhost;                    # my-site.com
        root  /usr/share/nginx/html;
    }
    server {
        listen  443 ssl;
        server_name  localhost;                   # my-site.com;
        ssl_certificate /certs/tls.crt;           # fullchain.pem
        ssl_certificate_key /certs/tls.key;       # privkey.pem
        root /usr/share/nginx/html;
    }
}
Để ý file cấu hình này, thiết lập nginx lắng nghe yêu cầu gửi đến cổng 80 và 443 (tương ứng với 2 server), thư mục gốc làm việc mặc định của chúng là /usr/share/nginx/html, tại đây sẽ copy và một file index.html
2) Chuẩn bị file index.html
index.html
<!DOCTYPE html>
<html>
<head><title>Nginx -  Test!</title></head>
<body>
    <h1>Chy Nginx trên Kubernetes</h1>    
</body>
</html>
3) Xây dựng image mới
Tạo Dockerfile xây dựng Image mới, từ image cơ sở nginx:1.17.6, có copy 2 file nginx.confindex.html vào image mới này
Dockerfile
FROM nginx:1.17.6
COPY nginx.conf /etc/nginx/nginx.conf
COPY index.html /usr/share/nginx/html/index.html
Build thành Image mới đặt tên là ichte/swarmtest:nginx (đặt tên theo tài khoản của bạn trên Hub Docker, hoặc theo cấu trúc Registry riêng nếu sử dụng) và push Image nên Docker Hub
# build image từ Dockerfile, đặt tên image mới là ichte/swarmtest:nginx
docker build -t ichte/swarmtest:nginx -f Dockerfile .

# đẩy image lên hub docker
docker push ichte/swarmtest:nginx

Tạo Deployment triển khai các Pod chạy ichte/swarmtest:nginx

6.nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: ichte/swarmtest:nginx
        imagePullPolicy: "Always"
        resources:
          limits:
            memory: "128Mi"
            cpu: "100m"
        ports:
        - containerPort: 80
        - containerPort: 443
Khi triển khai file này, có lỗi tạo container vì trong cấu hình có thiết lập SSL (server lắng nghe cổng 443) với các file xác thực ở đường dẫn /certs/tls.crt, /certs/tls.key nhưng hiện tại file này không có, ta sẽ sinh hai file này và đưa vào qua Secret

Tự sinh xác thực với openssl

Xác thực SSL gồm có server certificateprivate key, đối với nginx cấu hình qua hai thiết lập ssl_certificatessl_certificate_key tương ứng ta đã cấu hình là hai file tls.crt, tls.key. Ta để tên này vì theo cách đặt tên của letsencrypt.org, sau này bạn có thể thận tiện hơn nếu xin xác thực miễn phí từ đây.
Thực hiện lệnh sau để sinh file tự xác thực
openssl req -nodes -newkey rsa:2048 -keyout tls.key  -out ca.csr -subj "/CN=xuanthulab.net"
openssl x509 -req -sha256 -days 365 -in ca.csr -signkey tls.key -out tls.crt
Đến đây có 2 file tls.keytls.crt

Tạo Secret tên secret-nginx-cert chứa các xác thực

Thi hành lệnh sau để tạo ra một Secret (loại ổ đĩa chứa các thông tin nhạy cảm, nhỏ), Secret này kiểu tls, tức chứa xác thức SSL
kubectl create secret tls secret-nginx-cert --cert=certs/tls.crt  --key=certs/tls.key
Secret này tạo ra thì mặc định nó đặt tên file là tls.crttls.key có thể xem với lệnh
kubectl describe secret/secret-nginx-cert

Sử dụng Secret cho Pod

Đã có Secret, để POD sử dụng được sẽ cấu hình nó như một ổ đĩa đê Pod đọc, sửa lại Deployment 6.nginx.yaml như sau:
6.nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      volumes:
        - name: cert-volume
          secret:
             secretName: "secret-nginx-cert" 
      containers:
      - name: nginx
        image: ichte/swarmtest:nginx
        imagePullPolicy: "Always"
        resources:
          limits:
            memory: "128Mi"
            cpu: "100m"
        ports:
        - containerPort: 80
        - containerPort: 443 
        volumeMounts:
          - mountPath: "/certs"
            name: cert-volume 

Tạo Service truy cập kiểu NodePort

Thêm vào cuỗi file 6.nginx.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
spec:
  type: NodePort
  ports:
  - port: 8080        # cổng dịch vụ ánh xạ vào cổng POD
    targetPort: 80    # cổng POD ánh xạ vào container
    protocol: TCP
    name: http
    nodePort: 31080   # cổng NODE ánh xạ vào cổng dịch vụ (chỉ chọn 30000-32767)

  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
    nodePort: 31443
  # Chú ý đúng với Label của POD tại Deployment
  selector:
    app: nginx
Giờ có thể truy cập từ địa chỉ IP của Node với cổng tương ứng (Kubernetes Docker thì http://localhost:31080 và https://localhost:31443)
kubernetes

Đăng ký theo dõi ủng hộ kênh
Thứ Năm, 5 tháng 12, 2019

Sử dụng K9S công cụ quản lý Kubernetes Cluster

Thứ Tư, 4 tháng 12, 2019

Cài đặt và sử dụng Kubernetes Dashboard

Cài đặt DashBoard trên hệ thống đầy đủ

Kubernetes Dashboard là công cụ trên nền Web, kết nối đến Kubernetes để thực hiện việc quản lý (giống kubectl), ưu điểm của nó là trực quan dễ sử dụng. Thông tin chính về nó tại dashboard, các phiên bản Dashboard Release

https://xuanthulab.net/cai-dat-va-su-dung-kubernetes-dashboard.html



Cài đặt Kubernetes Dashboard trên Cluster



Để triển khai Kubernetes trước tiên lấy file cấu hình bản phù hợp về tại Dashboard Release, giả sử chọn v2.0.0-beta6 thì file cấu hình triển khai là:

https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml
Tải file này về lưu thành tên dashboard-v2-beta6.yaml
curl https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml > dashboard-v2-beta6.yaml
Mở file đó ra chỉnh các nội dung sau:
Nhiều phần trong quá trình chỉnh sửa như các khái niệm Pod, Service ... bạn có thể vẫn chưa hiểu ở giai đoạn này nhưng hãy cố thực hiện đúng - những khái niệm đó sẽ là nội dung chính của Kubernetes tìm hiều sau!

Thiết lập cho truy cập Dashboard qua địa chỉ IP các Node
Mặc định dịch vụ này không truy cập trực tiếp qua IP máy mà phải qua proxy, mở file dashboard-v2-beta6.yaml, tìm đến phần kind: Service bên trong có tên name: kubernetes-dashboard sửa thành:
---

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  # Đổi kiểu sang NodePort
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      # Chọn cổng truy cập qua Node là 3100
      nodePort: 31000
  selector:
    k8s-app: kubernetes-dashboard

---
Do cấu hình mặc định của Kubernetes Cluster, cổng được mở ra ngoài phải chọn trong khoảng 30000-32767 sau này bạn có thể sửa cấu hình này với tham số chạy Cluster --service-node-portrange
Xóa Secret có tên kubernetes-dashboard-certs
Đoạn cấu hình này để khởi tạo Secret cấu hình xác thực SSL khi truy cập Dashboard, ta xóa nó đi bằng cách comment như sau:
# ---

# apiVersion: v1
# kind: Secret
# metadata:
#   labels:
#     k8s-app: kubernetes-dashboard
#   name: kubernetes-dashboard-certs
#   namespace: kubernetes-dashboard
# type: Opaque
Sau này sẽ tạo thủ công Secret có tên kubernetes-dashboard-certs thủ công từ certificates sinh ra từ OpenSSL.
Triển khai dashboard-v2-beta6.yaml
Bây giờ ta sẽ triển khai các thành phần định nghĩa, cấu hình trong dashboard-v2-beta6.yaml, bạn thực hiện lệnh:
kubectl apply -f dashboard-v2-beta6.yaml
kubernetes
Tạo kubernetes-dashboard-certs, xác thực SSL
Ta sẽ dùng OpenSSL để sinh certificates tự xác thực SSL (ngoài ra khi triển khai thực tế có thể lấy các certificate do mua hoặc miễn phí từ https://letsencrypt.org/ theo Domain), chạy các lệnh sau:
sudo mkdir certs
sudo chmod 777 -R certs
openssl req -nodes -newkey rsa:2048 -keyout certs/dashboard.key -out certs/dashboard.csr -subj "/C=/ST=/L=/O=/OU=/CN=kubernetes-dashboard"
openssl x509 -req -sha256 -days 365 -in certs/dashboard.csr -signkey certs/dashboard.key -out certs/dashboard.crt
sudo chmod -R 777 certs
Trên Windows nếu không có lệnh openssl có thể tạo một Image có cài OpenSSL ví dụ Dockerfile sau:
FROM alpine

RUN apk update && \
  apk add --no-cache openssl && \
  rm -rf /var/cache/apk/*

ENTRYPOINT ["openssl"]
Sau khi hoàn thành thì các thông tin certificate lưu ở thư mục certs, chạy lệnh sau để tạo Secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=certs -n kubernetes-dashboard
Giờ truy cập địa chỉ https://192.168.10.100:31000 sẽ vào màn hình đăng nhập
kubernetes
Lấy Token đăng nhập Dashboard
Tạo một file có tên admin-user.yaml cập nhật nội dung sau:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
Sau đó chạy lệnh:
kubectl apply -f admin-user.yaml
(Tham khảo: )
Tiếp theo chạy lệnh sau để lấy Token
kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
Copy toàn bộ đoạn Token để đưa vào đăng nhập
kubernetes kubernetes
Như vậy đã hoàn thành cài đặt, khi truy cập có thể bạn cần dùng trình duyệt khác Chrome vì nó chặn truy cập khi SSL là tự xác thực.

Dashboard với Kubernetes trong Docker Desktop

Đối với Docker Desktop chỉ việc chạy lệnh sau để cài đặt (Tất nhiên nếu muốn có thể thực hiện cách trên) :
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml
Sau đó chạy proxy
kubectl proxy
Truy cập địa chỉ sau để đăng nhập: http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

Để có Token đăng nhập bạn cũng cần làm theo cách trên, tức triển khai file admin-user.yaml, rồi chạy lệnh lấy Token
Tổng kết: đến đây bạn đã có thể dùng công cụ lệnh kubectl hoặc dùng Dashboard trực quan để làm việc với Cluster. Tuy nhiên, trước mắt hãy cố gắng dùng kubectl, sau khi thành thạo rồi hãy dùng Dashboard. Bản thân Dashboard có đủ thông tin từ Node, Pod, Deployment ... Bạn có thể cập nhật, scale hay deploy ứng dụng từ Dashboard.

Danh mục Gửi liên hệ

Loading...