Using Sealed Secrets in a Raspberry Pi Kubernetes Cluster

Sealed Secrets is a bitnami Kubernetes operator aimed to one-way encrypt secrets into sealed secrets so that they can be safely checked-in into GitHub or other VCS. It’s rather easy to install and use Sealed Secrets in a Kubernetes cluster on AMD64 architecture, but not so on my Raspberry Pi cluster.

First, the container image for the sealed-secrets-controller wasn’t built for ARM architecture. I managed to build it in my Raspberry Pi 2 with following commands:

git clone
cd sealed-secrets
# golang build tools are needed here
make controller.image
# you can tag it to your docker registry instead of mine
docker tag raynix/sealed-secrets-controller-arm:latest
docker push raynix/sealed-secrets-controller-arm

The next step is to use kustomize to override the default sealed-secrets deployment schema to use my newly built container image that runs on ARM

# kustomization.yaml
# controller.yaml is from
kind: Kustomization

namespace: sealed-secrets
  - name:
    newName: raynix/sealed-secrets-controller-arm
    newTag: latest
  - patch.yaml

  - controller.yaml
  - ns.yaml
# ns.yaml
# I'd like to install the controller into its own namespace
apiVersion: v1
kind: Namespace
  name: sealed-secrets
# patch.yaml
# apparently the controller running on Raspberry Pi 4 needs more time to initialize
apiVersion: apps/v1
kind: Deployment
  name: sealed-secrets-controller
        - name: sealed-secrets-controller
            initialDelaySeconds: 100

Then the controller can be deployed with command kubectl apply -k .

The CLI installation is much easier on a Linux laptop. After kubeseal is installed. The public key used to encrypt secrets can be obtained from the controller deployed above. Since I installed the controller in it’s own namespace sealed-secrets instead of the default kube-system the command to encrypt secrets is a bit different:

kubectl create secret generic test-secret --from-literal=username=admin --from-literal=password=password --dry-run -o yaml | \
  kubeseal --controller-namespace=sealed-secrets -o yaml > sealed-secrets.yaml

Then the generated file sealed-secrets.yaml can be deploy with kubectl apply -f sealed-secrets.yaml and a secret called test-secret will be created. Now feel free to check-in sealed-secrets.yaml into a public GitHub repository!


Customize the Kustomize for Kubernetes CRDs

I’ve introduced Kustomize in this earlier post, now I feel even happier because Kustomize can be even more customized for some CRDs(Custom Resource Definition). For instance, Kustomize doesn’t know how to handle Istio’s VirtualService object, but with some simple YAML style configurations it ‘learns’ to handle that easily.

# k8s service, ie. service.yaml
apiVersion: v1
kind: Service
  name: wordpress-svc
    app: wordpress
    - name: http
      port: 80
      targetPort: 8080
  type: NodePort
# istio virtual service. ie. virtual-service.yaml
kind: VirtualService
  name: wordpress-vs
    - wordpress
    - match:
      - uri: /
        - destination:
          host: wordpress-svc
            number: 80
# kustomize name reference, ie. name-reference.yaml
  - kind: Service
    version: v1
      - path: spec/http/route/destination/host
        kind: VirtualService
# main kustomize entry, ie. kustomization.yaml
kind: Kustomization
  - name-reference.yaml
namespace: wordpress
nameSuffix: -raynix

So in name-reference.yaml, kustomize will learn the host property in VirtualService will be linked to the of a service. When the name suffix -raynix is applied to the Service, it will also be applied to the VirtualService, eg.

kind: Service
  name: wordpress-svc-raynix

kind: VirtualService
    - route:
      - destination:
          host: wordpress-svc-raynix

For more information:



2020 新年快乐!!我不得不重复的说,时间过的太快了。其中的一个原因大概是我离开我舒适的环境去接受新的挑战。

2019年初我从 AFL 离职后加入了云计算顾问公司 Contino,想给自己找点挑战,结果还真是很挑战。我从来没做过顾问,因为我性格内向而且英语交流也仅仅达到及格的水平,我想一定是之前的技术经验为我赢得了这份工作。

入职后不久我就被派到一家4万多人的大企业做云迁移项目,就是将原本运行在 IBM 硬件上的业务系统搬迁到 AWS 上继续运行。这回算是体验到了 IBM 的傲慢,知道大客户要投奔 AWS 了也并不在意,但也不是很大方的提供技术上的支持就是了。在大企业里很多事情靠的不是技术而是人际关系和政治头脑,而我在这些方面基本属于幼稚园毕业。好在同事们非常有团队精神,帮我度过了最初几个月。后来我有幸参加了公司的软技能培训,收获非常大,瞬间意识到自己以前说话的方式有多么简陋。


在猫本的第一份工作期间我的一个同事 G 就是素食者。当时我们几个“正常人”总是开他的玩笑,例如:素汉堡不算汉堡。但至少我从此有了一个素食朋友。最近几年老婆将后院菜园种的有声有色,各种蔬菜直接从菜园进厨房,真正的新鲜蔬菜。我当然还是爱吃肉的,但老婆收获的蔬菜是必须吃的,所以我吃蔬菜的比例有了很大提高。令我感到意外的是,吃蔬菜的感觉还真不错。

与此同时,肉食产品的负面新闻接踵而来:禽流感,猪瘟,过度放牧,抗生素饲料等等。这些让我对吃肉的兴趣有所减弱。直到我看了 NetFlix 上的纪录片 The Game Changers ,我了解到了很多最强的人,例如运动员,铁人五项冠军等等都不吃肉:“很多人问我,你如何只吃素却像牛一样强壮?我反问,你见过牛吃肉吗?” 没错,就像“钻石恒久远 一颗永流传”一样,让人们喜欢吃肉也是市场运作的结果。


Use fzf to Supercharge Your kubectl Command

First let’s have a look at fzf, a super fast command line fuzzy finder. It’s mostly written in golang and there are so many ways to use it. In this note, I’ll just use it to select a value from a list in a terminal and then return it to next command.

When working with kubernetes, I open need to switch between namespaces in a cluster. The raw kubectl command for this is:

 kubectl config set-context --current --namespace='my-namespace'

But I don’t remember every namespace, do I? If auto-completion of kubectl is available I can double-tab and then get a list of namespaces like this:

This is not quite convenient, not at all. So I created this simple bash function using fzf to speed this up.

#select k8s namespace
function kns() {
  kubectl config set-context --current --namespace=$(kubectl get namespaces --output=jsonpath='{range .items[*]}{}{"\n"}'|fzf)

The kubectl get... command in the sub shell above simple output a list of available kubernetes namespaces and then pipe to fzf to make an interactive auto-completion. And then the selected namespace will be passed back to kubectl config ... command to actually set the namespace to current context. The result looks like this:

PS. I’ve put this and other handy shorthand functions here.