20190329124004
04Th3

Những điều cần biết về kube2iam

How To Set Up Iam On Aws Account Complete Step By Step Guide

 

Xin chào các bạn,

Tôi là Tsutomu Kikuchi thành viên đội Infrastructure – một anh chàng đam mê Honda F1 và động cơ Renault nhưng lại không có tiền để mua gói DAZN và Fuji TV NEXT đây ~~

Tại PIXTA, Amazon Web Service được sử dụng làm nền tảng cơ sở hạ tầng, nhưng cho đến nay, tài nguyên máy chủ (EC2) cho mỗi dịch vụ chủ yếu được xây dựng bằng OpsWorks. Mặc dù OopWorks đang rất phổ biến trong thời gian gần đây nhưng chúng tôi nhận thấy nó còn tồn tại nhiều hạn chế. Chính vì vậy chúng tôi đã nghiên cứu để xây dựng cơ sở hạ tầng bằng cách đóng gói các application (sử dụng container thay cho OpsWorks).

Sau khi đưa Docker vào xây dựng môi trường phát triển, hiện tại chúng tôi đang tiếp tục xây dựng môi trường container mà sử dụng kubernetes (dưới đây gọi tắt là k8s) dành cho môi trường staging/production. Trong bài viết lần này, tôi muốn giới thiệu và giải quyết vấn đề về IAM Role (instance profile) mà bạn có thể gặp phải khi chuyển một application chạy trên EC2 sang Clusters K8s cũng chạy trên EC2.

Instance profile trên k8s

Các ứng dụng (application) tạo nên các dịch vụ của PIXTA chủ yếu được xây dựng trên nền tảng AWS, nên ngoài EC2 chúng tôi cũng sử dụng một số tài nguyên AWS khác như S3… Quyền truy cập cần khi một application truy cập vào những tài nguyên trên, nhưng về cơ bản thì PIXTA sẽ sử dụng Instance profile để chuyển quyền truy cập vào application. Đối với mỗi application, chúng tôi sẽ tạo một IAM role và sử dụng Instance profile để gắn nó với instance đó.

Trong cấu hình hiện tại, các instance chạy trên mỗi application đều khác nhau, và mỗi application đều yêu cầu có quyền truy cập. Đây cũng là cách được khuyến nghị để chuyển quyền truy cập vào những tài nguyên khác nhau cho application của bạn. Tuy nhiên, việc đóng gói hết các application và đặt chúng trong các Clusters K8s tên EC2 theo đơn vị pod hay deployment cũng không hề dễ dàng chút nào. Trong Clusters K8s, một số lượng container không xác định sẽ chạy trên cùng một instance, nhưng thật không may, hiện tại không có một quy trình chuẩn nào để chuyển IAM Role trên cho các đơn vị pod hay development

Nếu không làm gì, mỗi container trên cluster sẽ nhận được 1 instance profile tương ứng với instance đó (container đó chính là worker node instance đang được chạy), hay nói cách khác là nhận được IAM Role của node mà nó đang chạy trên đó. Và đó chính là vấn đề chúng ta cần chú ý! Sau đây tôi sẽ đưa ra một ví dụ đơn giản để giúp các bạn dễ hình dung hơn nhé!

Ví dụ:

  • Giả sử bạn có Pod: A cần truy cập bucket S3 có tên A. Nếu bạn cấp quyền truy cập vào bucket A cho IAM Role đang được gán cho worker node, Pod: A sẽ có thể truy cập bucket A.
  • Giả sử bạn cũng thêm Pod: B vào cùng một cluster, cần truy cập vào bucket trên S3 có tên B. Lần này, nếu cấp quyền truy cập vào bucket B cho IAM Role đang được gán cho worker node, Pod: B sẽ có thể truy cập nhóm B.

Tuy nhiên, tại thời điểm này, Pod: A cũng sẽ có quyền truy cập vào nhóm B và Pod: B cũng có quyền truy cập vào nhóm A.

 

f: id: pixta-kikuchi: 20190329124004p: đồng bằng

Chú thích: Pod A và Pod B đều được cấp quyền giống nhau nên cả 2 đều có thể truy cập vào cả bucket A và B

Do đó, nếu bạn chỉ cố gắng ủy quyền cho các container bằng cách dùng instance profile và IAM Role trên k8s cluster trong EC2, thì mỗi khi một application được thêm vào cluster, các container sẽ được chia sẻ IAM Role, đôi khi các container có chia sẻ chung một IAM Role. Tuỳ từng trường hợp sẽ phát sinh ra những container có nhiều quyền cùng lúc. Đây là một tình huống đầy rủi ro đối với việc bảo mật, có thể dẫn đến lỗi hoặc sự cố trong application.

 

Giới thiệu về kube2iam

https://github.com/jtblin/kube2iam

Khái quát

kube2iam cũng chạy như một container (daemonset) trong k8s cluster. Bạn có thể đưa kube2iam vào sử dụng bằng cách public image docker và tự định nghĩa các manifest cần thiết (như yalm của daemonset), nhưng thường thì nó sẽ được phân phối dưới dạng helm chart. Nếu môi trường có thể sử dụng helm thì bạn có thể cài đặt từ helm.

Cơ chế hoạt động

kube2iam làm trung gian gửi yêu cầu instance meta data từ mỗi container. Cụ thể, khi được deploy trên các node, nó sẽ thêm phần cài đặt iptables trên mỗi node đó. Bằng cách này, kube2iam container sẽ thu thập tất cả request lấy thông tin xác thực giống như: http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME từ các container, xử lý chúng khi thích hợp và trả lại cho người request.

 

f: id: pixta-kikuchi: 20190329124125p: đồng bằng

Chú thích: Pod A và Pod B được cấp quyền khác nhau qua trung gian kube2iam, do đó mỗi Pod chỉ có thể access vào 1 bucket A hoặc B tương ứng

   

Trong cụm nơi kube2iam đã được cài đặt, có thể cấp quyền cho mỗi pod hoặc developement bằng cách chỉ định IAM Role mà bạn muốn cấp cho annotation như dưới đây:

apiVersion: v1

kind: Pod

metadata:

name: mypod

annotations:

iam.amazonaws.com/role: role-arn

Chú ý: Cần phải thiết lập chính sách uỷ thác giữa các IAM Role khác biệt.

 

Những vấn đề gặp phải khi vận hành

Mặc dù đã apply kube2iam nhưng chúng tôi cũng gặp phải 1 số vấn đề phát sinh. Việc đưa vào sử dụng khá là đơn giản, như tôi đã nói ở trên việc sử dụng cơ chế iptables đem lại hiệu quả khá tốt. Và tôi muốn chia sẻ với các bạn tất cả những việc cần chú ý trước khi application kube2iam.

  • Mặc dù đã xoá nhưng IPtables vẫn không thay đổi

Khi đưa vào sử dụng, mặc dù tôi đã xoá kube2iam nhưng setting của iptables vẫn còn nguyên. Thật là rắc rối khi cần phải chuyển trạng thái về như trước khi áp dụng nhưng tôi buộc phải xoá iptables bằng cách thủ công. Nhân đây tôi cũng chia sẻ với các bạn câu lệnh xoá luôn. (Nói thật là lâu lắm rồi tôi mới gõ câu lệnh cho iptables)

// kiểm tra setting của iptables

# iptables-save | grep 169.254

// Kiểm tra setting record tương ứng

# iptables -t nat -L PREROUTING –line-numbers

〜Lược bỏ〜

4 DNAT tcp — anywhere instance-data.ap-northeast-1.compute.internal tcp dpt:www to:172.16.105.32:8181

// Xoá dòng tương ứng

# iptables -t nat -D PREROUTING 4

 

  • Xung đột giữa ingress và bot khi thêm worker node

Khi một worker node nào đó được thêm vào, kube2iam có vẻ triển khai khá ổn, nhưng lại phát sinh vấn đề ingress không khởi động được.

Về môi trường, cluster được xây dựng trên EC2 bằng cách sử dụng Rancher (v2.1.6), kube2iam cũng được cài đặt helm (catalog) từ GUI của Rancher. Có thể nói image của ingress chính là: rancher/nginx-ingress-controller:0.16.2-rancher1

Nguyên nhân là do cổng 8181 đang dùng kube2iam gây ra. Thường thì cổng 8181 không được sử dụng, nhưng lần này khi bật ingress kube2iam thì đã thực hiển kiểm tra cổng 8181 và dẫn đến hiện tượng không thể khởi động được. Kube2iam mặc định dùng cổng 8181 nên khi thêm worker, kube2iam được ưu tiên hơn so với ingress và bật lên trước nên gây nên lỗi. Chỉ cần ingress được bật lên trước thì sẽ không có vấn đề gì. Chúng ta có thể khởi động được cả ingress và sau đó là kube2iam. Vi có thể thay đổi cổng cho kube2iam nên tôi đã thử đổi sang cổng 8182 nhưng dù thế nào đi nữa nó vẫn tự động lấy cổng 8181. Và lỗi vẫn lặp lại. Không còn cách nào khác, tôi đã thêm setting initContainers bên trong daemonset.yam của kube2iam, để nó chờ đến khi ingress khởi động xong. (Từ trước cho tới nay, tôi đã cài đặt bằng helm, nhưng đến đây tôi đã từ bỏ).

initContainers:

– name: ingress-check

image: busybox

command: [‘sh’, ‘-c’, ‘until wget –spider http://$(HOST_IP)/healthz; do echo waiting for ingress start; sleep 1; done;’]

env:

– name: HOST_IP

valueFrom:

fieldRef:

fieldPath: status.podIP

Access key của IAM user

Trong bài viết này tôi đã giới thiệu về cách chuyển quyền cho mỗi pod hay developemt bằng kube2iam method, nhưng ngoài ra vẫn còn rất nhiều cách cấp quyền cho application khác mà chúng ta có thể sử dụng.

Chắc cũng có nhiều bạn nhận ra rằng: thay vì chuyển IAM Role, chúng ta chỉ cần cung cấp access key của người dùng IAM- người đã được cấp quyền mà application cần. Đây là cách truyền các biến môi trường của các container. Có thể nói đây là một phương pháp vô cùng đơn giản và đáng tin cậy hay có thể nói là khá ổn định vì nó không phụ thuộc vào kube2iam. Tuy nhiên, ban đầu AWS không khuyến khích phương pháp sử dụng Access key, mà khuyến khích chuyển IAM Role bằng những cách liên quan đến instance sử dụng instance profile.

Cá nhân tôi cũng cho rằng so với cách sử dụng instance profile, việc access key được lấy ra một cách quá dễ dàng cũng là 1 trong những rủi ro về mặt bảo mật thông tin, chính vì vậy tôi cũng khá e dè và đắn đo nếu phải chuyển từ cách dùng instance profile sang dùng access key. Access key là thông tin quan trọng nên cần phải quản lí chặt ché và vận hành nó một cách hợp lí, bạn cũng cần bổ sung tài liệu hướng dẫn truyền access key như là 1 biến số môi trường đến container (ví dụ như: cách tạo secret object…). Khi tôi biết được kube2iam sử dụng iptables tôi đã thấy hơi lo lắng và bất an, tôi nghĩ mình có thể sử dụng acess key, nhưng vì những lí do trên vẫn tiếp tục thử kube2iam vì tôi muốn giữ nguyên IAM Role như đã từng làm trước đây.

 

Lời kết

Tôi nghĩ rằng cũng có nhiều công ty muốn chuyển các application đang chạy trên EC2 sang container, và chuyển sang Cluster K8s trên EC2 cũng đang gặp những vấn đề tương tự như PIXTA mà tôi đã giới thiệu ở trên. Đối với tôi, thì ở thời điểm hiện tại tôi cũng không dám chắc đây là phương pháp tốt nhất, nhưng tôi hy vọng bài viết này có thể cung cấp những thông tin hữu ích để bạn có thể cân nhắc việc có sử dụng kube2iam hay không?

Cảm ơn các bạn đã theo dõi bài viết! 

 

Tác giả: Tsutomu Kikuchi (PIXTA Inc.)

Bài viết gốc: tại đây

Người dịch: Khuyên Nguyễn, Hoàng Lân

Like và follow fanpage của Pixta Việt Nam để cập nhật các thông tin công nghệ hữu ích nhé!