[Nhập môn Kubernetes P11] - Quản lý Container Images bảo mật với Harbor
Serial blog Nhập môn Kubernetes
Nội dung
- Giới thiệu Harbor
- Cài đặt Harbor
- Sử dụng Harbor
- Demo pull image với Kubernetes.
- Kết luận
- Tài liệu tham khảo
Giới thiệu Harbor
Bạn có đang sử dụng Docker Images? Tại thời điểm này Images mà bạn đang sử dụng có nguy cơ tiềm ẩn những lỗ hổng bảo mật và có thể bị khai thác.
Harbor là một open source cloud native registry, dùng để lưu trữ, đánh dấu, scan các container images để phát hiện các lỗ hổng bảo mật.
Harbor giải quyết các thách thức phổ biến bằng cách cung cấp sự tin cậy (trust), sự tuân thủ, hiệu suất và khả năng tươnng tác.
Như các bạn đã biết, docker hub, docker cloud là những docker registry để chúng ta pull, push image. Hầu hết các image chúng ta sử dụng là public images, nếu như muốn sử dụng private có lẽ phải tốn phí. Harbor cung cấp giải pháp để chúng ta tạo một private/public docker registry một cách đơn giản. Điều này sẽ bảo mật cho project của các doanh nghiệp rất tuyệt vời.
Trang chủ: https://goharbor.io/
Một số tính năng nổi bật:
- Ký và validation nội dung với nhiều bên
- Phân tích các vấn đề security và các lỗ hổng bảo mật
- Tích hợp nhận dạng và kiểm soát truy cập bằng role-based
- Sao chép images giữa các máy
- Cung cấp API và giao diện thân thiện
- Hiện thị nhiều ngôn ngữ (Hiện tại có Anh, Trung Quốc, Pháp, Tây ban Nha)
Kiến trúc Harbor
Nhiều tính năng pro quá, tạm thời chúng ta sẽ quan tâm đến chức năng cơ bản và đầu tiên, đó là một private docker-registry dùng để pull, push images một cách bảo mật, tính năng tạo project, tạo user, add user vào project.
Cài đặt Harbor
Yêu cầu phần cứng
- CPU: ít nhất 2 CPU
- Mem: ít nhất 4GB
- Disk: ít nhất 40GB
Yêu cầu phần mềm
- Python: 2.7 hoặc hơn
- Docker engine: 1.10 hoặc hơn
- Docker compose: 1.7.0 hoặc hơn
- Openssl: latest càng tốt.
Cài đặt
Các bạn cần chuẩn bị máy ảo hoặc VPS có cấu hình như yêu cầu nhé. Sau khi đã chuẩn bị xong phần cứng và phần mềm, chúng ta tiến hành cài đặt Harbor.
Tham khảo:
https://github.com/goharbor/harbor/blob/master/docs/installation_guide.md
Lưu ý: thư mục và các file bên trong harbor/ mà installer giải nén ra (kể cả chính nó) phải có owner là root, nếu không sẽ bị lỗi owner unknown trong các container.
$ sudo chown root:root /path/to/harbor
$ sudo chown root:root /path/to/harbor/*
Tạo ssl certificate cho registry
- Tạo một thư mục chứa các certificate file
$ sudo mkdir certs/
$ cd certs/
- Tự tạo CA (Certificate Authority)
$ sudo openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout ca.key \
-x509 -days 365 -out ca.crt
# Lưu ý phải nhập hết trừ Optional
- Yêu cầu một Certificate Signing Request
- Nếu dùng domain cho registry thì có lưu ý là mục Common Name (CN) trong khi nhập phải là domain muốn dùng. Còn nếu dùng ip cho registry thì nhập bất kì tùy thích.
$ sudo openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout yourdomain.com.key \
-out yourdomain.com.csr
- Tạo certificate cho registry host
- Nếu dùng domain
$ sudo openssl x509 -req -days 365 -in yourdomain.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out yourdomain.com.crt
- Nếu dùng IP, thay IP muốn dùng sau dòng IP:
$ echo subjectAltName = IP:35.xxx.xxx.xxx > extfile.cnf
$ sudo openssl x509 -req -days 365 -in yourdomain.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out yourdomain.com.crt
- Ở mỗi docker host muốn sử dụng registry này, copy file ca.crt vào đường dẫn sau /etc/docker/certs.d/[domain_OR_ip]/ca.crt
Ở đây mình đang dùng IP và thự hiện test trên máy hiện tại luôn (Các docker host khác muốn pull image từ docker-registry này thì cũng tạo đường dẫn và file như bên dưới)
$ cp /path/to/certs/ca.crt /etc/docker/certs.d/35.xxx.xxx.xxx/ca.crt
- Bước này giúp các docker host trust certificate mà chúng ta sẽ dùng cho registry.
Cấu hình và khởi động Harbor
- Quay lại máy muốn chạy Harbor, tải bộ cài tại https://github.com/goharbor/harbor/releases rồi giải nén
$ sudo wget https://storage.googleapis.com/harbor-releases/release-1.6.0/harbor-online-installer-v1.6.0.tgz
$ tar xvf harbor-online-installer-v1.6.0.tgz
$ cd harbor/ # vào thư mục mới giải nén
- Chỉnh sửa file harbor.cfg với các config cơ bản sau
$ sudo vi harbor.cfg
# domain hoặc ip muốn dùng cho registry
hostname = 35.xxx.xxx.xxx
# giao thức kết nối UI Harbor
ui_url_protocol = https
......
# Đường dẫn đến 2 file certificate .crt và .key đã tạo phía trên
ssl_cert = /path/to/certs/yourdomain.com.crt
ssl_cert_key = /path/to/certs/yourdomain.com.key
# Đường dẫn chứa secret của các container
secretkey_path = /data
- Chạy script cài đặt và khởi động các container
$ sudo ./install.sh
Trường hợp lệnh trên không chạy được thì thực hiện theo issue bên dưới.
https://github.com/goharbor/harbor/issues/2317
$ sudo -E env "PATH=$PATH" ./install.sh
Chú ý: Nếu bạn muốn cài đặt các dịch vụ Notary, Clair và chart bạn phải chỉ định các tham số tương ứng
$ sudo -E env "PATH=$PATH" ./install.sh --with-notary --with-clair --with-chartmuseum
Để hiểu về Notary và Docker Content Trust bạn tham khảo ở đây:
https://docs.docker.com/engine/security/trust/content_trust/
Để hiểu về Clair, bạn hãy tham khảo Clair's documentation: https://coreos.com/clair/docs/2.0.1/
- Khi đó truy cập vào domain hoặc ip đã dùng cho registry trên trình duyệt để vào Harbor UI
https://35.xxx.xxx.xxx/
- Lưu ý user/password mặc định là: admin/Harbor12345 .
Sau khi truy cập vào chúng ta có thể change password/tạo thêm user vv.
Sử dụng Harbor
Chi tiết:
https://github.com/goharbor/harbor/blob/master/docs/user_guide.md
Sau khi đã đăng nhập thành công, chúng ta có giao diện như sau:
Các bạn có thể tự tìm hiểu cách sử dụng qua tài liệu chi tiết, ở đây mình sẽ demo một số thao tác cơ bản như tạo user/project pull/push image.
Create user
Role Based Access Control(RBAC)
Harbor quản lý images thông qua Project. User có thể được thêm vào một project với tư cách là một member với 3 quyền sau:
-
Guest: Khách có đặc quyền chỉ đọc cho một dự án cụ thể.
-
Developer: Developer có đặc quyền đọc và viết cho một dự án.
-
ProjectAdmin: Khi tạo một dự án mới, bạn sẽ được gán vai trò "ProjectAdmin" cho dự án. Bên cạnh đặc quyền đọc-ghi, "ProjectAdmin" cũng có một số đặc quyền quản lý, chẳng hạn như thêm và xóa thành viên, bắt đầu quét lỗ hổng.
Bên cạnh ba vai trò trên, có hai vai trò trên toàn hệ thống: -
SysAdmin: "SysAdmin" có nhiều đặc quyền nhất. Ngoài các đặc quyền được đề cập ở trên, "SysAdmin" cũng có thể liệt kê tất cả các dự án, đặt người dùng thông thường là quản trị viên, xóa người dùng và đặt chính sách quét lỗ hổng cho tất cả images. Project public "library" cũng thuộc sở hữu của quản trị viên.
-
Anonymous (Ẩn danh): Khi người dùng không đăng nhập, người dùng được coi là người dùng "Ẩn danh". Người dùng ẩn danh không có quyền truy cập vào các dự án private và có quyền truy cập chỉ đọc vào các dự án public.
- Tại menu User bên trái -> click button NEW USER và nhập các thông tin để create user. (mình tạo user phongnx, pass: phongnxpassword)
- Menu Project -> click NEW PROJECT, mặc định là private project. (ở đây mình đặt tên là kube-demo)
- Chọn project kube-dome -> menu ngang "Member" -> click "+ User" -> điền tên user đã tạo lúc nãy "phongnx" chọn role là Develop/Project Admin -> OK
Vậy là chúng ta cơ bản đã tạo user và project rồi, bây giờ chúng ta sẽ thực hiện login push/pull image ở docker host.
Tại docker host: (là máy chúng ta đang cài Harhor hoặc một máy khác có cài docker), lưu ý là file /etc/docker/certs.d/35.xxx.xxx.xxx/ca.crt đã được tạo.
Ở giao diện Harbor chúng ta chọn project "kube-demo" chọn menu phía trên là "Repositories" -> click vào chữ "PUSH IMAGE" ở góc bên phải sẽ hiện ra cho chúng ta cách đổi tên image trên docker host và cách push lên docker-registry (harbor) đúng format:
Làm thử thôi !!!
# pull image ở docker hub
$ docker pull ubuntu:16.04
# Làm theo hướng dẫn ở Harbor để thay đổi tên image
$ docker tag ubuntu:16.04 35.xxx.xxx.xxx/kube-demo/my-ubuntu
# Kiểm tra tên đã đổi chưa
$ docker images
# Login vào docker-registry (harbor)
$ docker login -u phongnx -p phongnxpassword 35.xxx.xxx.xxx
Login Succeeded
# Push image to Harbor
$ docker push 35.xxx.xxx.xxx/kube-demo/my-ubuntu
# Pull image từ docker host khác/hoặc xoá image trên host hiện tại để test pull image từ Harbor
$ docker rmi 35.xxx.xxx.xxx/kube-demo/my-ubuntu
# confirm delete
$ docker images
# pull image from Harbor
$ docker pull 35.xxx.xxx.xxx/kube-demo/my-ubuntu
Vậy là OK rồi !!!
Demo pull image với Kubernetes.
Nãy giờ mình hoàn toàn chưa đề cập gì đến Kuberbetes nhỉ. Sau đây mình sẽ làm một demo nhỏ để thấy được việc pull image từ docker-registry được thực hiện như thế nào.
Các bạn xem lại kiên trúc K8s-cluster mình tạo ở phần 3 với Rancher 2.0
https://blog.vietnamlab.vn/2018/09/04/nhap-mon-kubernetes-p3-rancher-2-0-kien-truc-k8s/
Kiến trúc của chúng ta bây giờ sẽ thêm anh chàng Harbor này vào nữa
lưu ý: tại các node chúng ta phải tạo file /etc/docker/certs.d/35.xxx.xxx.xxx/ca.crt để trust với harbor
Tạo một deployment
Nếu các bạn đang dùng minikube thì cũng Ok nhé. Còn kiến trúc như mình thì càng OK.
Ở Rancher server
Tạo file deployment-harbor_sample.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "app"
operator: In
values:
- "develop"
containers:
- name: nginx-container
image: 35.xxx.xxx.xxx/kube-demo/my-nginx
ports:
- containerPort: 80
imagePullSecrets:
- name: harbor-secret-registry
Do ở đây mình gắn nhãn lên Node để schedule container vào đúng Node. Nếu các bạn không gắn nhãn cho Node thì bỏ qua phần bên dưới
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "app"
operator: In
values:
- "develop"
Image mà chúng ta pull lần này là image đang có trên docker-registry của chúng ta: 35.xxx.xxx.xxx/kube-demo/my-nginx
Các bạn cũng sẽ để ý đến phần setting sau:
imagePullSecrets:
- name: harbor-secret-registry
harbor-secret-registry chính là khóa để kết nối với Harbor server, chúng ta sẽ tạo nó ngay dưới đây, nó chứa thông tin usernam, password và docker-registry hostname
Tạo secret
Đơn giản sẽ tạo như sau:
$ kubectl create secret docker-registry harbor-secret-registry --docker-server=35.xxx.xxx.xxx --docker-username=phongnx --docker-password=phongnxpasword --docker-email='phongnx@vietnamlab.vn'
# Kiểm tra lại
$ kubectl get secret
harbor-secret-registry kubernetes.io/dockerconfigjson 1 3h
Vậy là OK, các resource nào muốn pull images từ Harbor thì sẽ dùng key này.
Apply deployment
$ kubectl apply -f deployment-harbor_sample.yml
Kiểm tra đã pull image OK chưa
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sample-deployment-7d985644b8-bjjwg 1/1 Running 0 3h
sample-deployment-7d985644b8-lghbn 1/1 Running 0 3h
sample-deployment-7d985644b8-slhpn 1/1 Running 0 3h
Trong trường hợp phát sinh lỗi, Pods ở trạng thái không phải Running thì chúng ta có thể xem log.
$ kubectl describe pods {Not_Running_Pod_name}
Kết luận
Vậy là mình đã giới thiệu đến các bạn cách cài đặt và sử dụng Harbor như một docker-registry. Như các bạn cũng thấy đó, Harbor còn nhiều tính năng nổi bật, các bạn có thời gian hãy tìm hiểu thêm nhé.
Bài viết này mình cũng đã demo cách pull image từ Harbor kết hợp với Kubernetes, sau tất cả thì mọi chuyện dường như cũng có vẻ đơn giản nhỉ.
Với sự kết hợp của Rancher 2.0 và Harbor thì chúng ta càng ngày càng thấy thoải mái, và có thể vận dụng Kubernetes một cách linnh hoặt hơn, bảo mật hơn. Làm việc với giao diện cho chúng ta cái nhìn tổng quan, rõ ràng về hệ thống hơn.
Bài viết tiếp theo mình sẽ lại đề cập đến một Stack khá hay dùng để monitoring kết hợp với K8s, để mọi thứ càng trở nên sáng sủa :D.