Goal
[!TIP]
In hurry? Jump directly to Result section to see the outcome of this dive.
Athenz provides the following API endpoints for getting Athenz domain and its role/policy information:
/v1/domain/{domainName}/group/admin/v1/domain/{domainName}/group/viewer
However, if your applications are running in Kubernetes, constantly querying these endpoints can be inefficient. Ideally, you want a synchronization mechanism to cache this data within the cluster. Furthermore, you might want to decouple your applications from a direct dependency on Athenz to improve resilience.
Let's be realistic—building a custom client to fetch, cache, and manage these resources within Kubernetes is a hassle. Why reinvent the wheel when you just want to consume the data?
That's why I looked into Athenz/k8s-athenz-syncer. It is an existing tool designed to sync Athenz data into Kubernetes Custom Resources (CRDs) called AthenzDomain, effectively handling the heavy lifting for us. In this post, I’ll walk through how to deploy this syncer, fix a few build issues I encountered, and explore how it can save us from writing unnecessary boilerplate code.
- Goal
- Result
-
Setup
- Setup: Working directory
- Setup: Athenz and Local Kubernetes Cluster
- Test
- Setup: Set UI for web page
- Test
- Setup: Clone k8s-athenz-syncer
- Setup: Build image
- Setup: Load image to kind cluster
- Setup: Deploy manifests
- Test
- Setup: Create a secret to represent
k8s-athenz-syncer - Setup: Create our custom deployment
- Verify: Does it work?
- What I learned
- What's next?
- Dive Hours: 24.5 Hours
- Closing
Result
I successfully deployed k8s-athenz-syncer, and the AthenzDomain CRD was registered as follows:
Next, I created a domain named home.syncer and a role can-i-see-this-role-in-crd to see if syncer can really sync the AthenzDomain CRD:
Finally, I created a Kubernetes namespace home-syncer (Note: Athenz domains replace dots . with dashes - in K8s namespaces). I verified that the syncer successfully generated the AthenzDomain resource, with its roles and policies correctly synced:
Setup
Setup: Working directory
Let's set up the working directory. Feel free to use your own, but here is an idempotent script for a quick start:
test_name=deploy_k8s_athenz_syncer
tmp_dir=$(date +%y%m%d_%H%M%S_$test_name)
mkdir -p ~/test_dive/$tmp_dir
cd ~/test_dive/$tmp_dir
Setup: Athenz and Local Kubernetes Cluster
[!WARNING]
The following script only works on macOS. Let me know in comments if you want to use other platforms.
The following script will set up a local Kubernetes cluster and install the Athenz server:
git clone https://github.com/mlajkim/dive-manifest.git manifest
make -C manifest setup
Test
Let's verify that the Athenz server is running:
kubectl get pods -n athenz
Setup: Set UI for web page
To visualize the results later, let's set up port forwarding to access the Athenz UI in a browser:
kubectl -n athenz port-forward deployment/athenz-ui 3000:3000
Test
Open the UI in browser:
open http://localhost:3000
Setup: Clone k8s-athenz-syncer
[!NOTE]
Once the PR https://github.com/AthenZ/k8s-athenz-syncer/pull/45 is released, we will usemlajkim's fork.
git clone -b fix/deprecated-Dockerfile-images-and-CRD-definition-API https://github.com/mlajkim/k8s-athenz-syncer.git syncer
Setup: Build image
Let's build the image locally:
(cd syncer && docker build -t local/k8s-athenz-syncer:latest .)
Setup: Load image to kind cluster
Since we are using Kind, we need to load the locally built k8s-athenz-syncer image into the cluster:
kind load docker-image local/k8s-athenz-syncer:latest
# Image: "local/k8s-athenz-syncer:latest" with ID "sha256:bb5bcf2d9c362a46444f9476791f6c9e3f81ce6abf6ebc07d3228b9b7da53fa8" not yet present on node "kind-control-plane", loading...
Setup: Deploy manifests
[!TIP]
For the detailed explanation of each command, please refer to the following[!WARNING]
We will create a customdeployment.yamllater, as the sample provided in the OSS repository requires configurations that are a bit complex for a quick demo.
kubectl create ns kube-yahoo
kubectl apply -f ./syncer/k8s/athenzdomain.yaml
kubectl apply -f ./syncer/k8s/serviceaccount.yaml
kubectl apply -f ./syncer/k8s/clusterrole.yaml
kubectl apply -f ./syncer/k8s/clusterrolebinding.yaml
Test
[!TIP]
It is okay to seeNo resources foundat this stage, as the syncer managing theAthenzDomainis not yet deployed.
The commands above registered the AthenzDomain CRD (shortened to domain). Let's quickly check:
kubectl get domain
# No resources found
Setup: Create a secret to represent k8s-athenz-syncer
Unlike a standard production setup which uses CopperArgos to auto-distribute X.509 certificates, we will simply use the root certificate for this quick demo to represent k8s-athenz-syncer as an Athenz service.
kubectl create secret generic k8s-athenz-syncer-cert \
-n kube-yahoo \
--from-file=cert.pem=./athenz/certs/athenz_admin.cert.pem \
--from-file=key.pem=./athenz/keys/athenz_admin.private.pem \
--from-file=ca.pem=./athenz/certs/ca.cert.pem
# secret/k8s-athenz-syncer-cert created
Setup: Create our custom deployment
[!NOTE]
Note the following configurations:
- We set
zms-url=https://athenz-zms-server.athenz:4443/zms/v1because we are sharing the same Kubernetes cluster with the Athenz server- We set
update-cron=5sto see the synchronization results quickly
As mentioned earlier, we are using a custom manifest that mounts the Secret we just created:
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-athenz-syncer
namespace: kube-yahoo
labels:
app: k8s-athenz-syncer
spec:
replicas: 1
selector:
matchLabels:
app: k8s-athenz-syncer
strategy:
rollingUpdate:
maxSurge: 50%
maxUnavailable: 0%
type: RollingUpdate
template:
metadata:
labels:
app: k8s-athenz-syncer
spec:
containers:
- name: syncer
image: local/k8s-athenz-syncer
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 1
memory: 1Gi
args:
- --zms-url=https://athenz-zms-server.athenz:4443/zms/v1
- --update-cron=5s
- --cert=/var/run/athenz/cert.pem
- --key=/var/run/athenz/key.pem
- --cacert=/var/run/athenz/ca.pem
- --exclude-namespaces=kube-system,kube-public,kube-k8s-athenz-syncer,default,local-path-storage,kube-node-lease,athenz,ajktown-api,kube-yahoo
volumeMounts:
- name: athenz-certs
mountPath: /var/run/athenz
readOnly: true
serviceAccountName: k8s-athenz-syncer
volumes:
- name: athenz-certs
secret:
secretName: k8s-athenz-syncer-cert
EOF
# deployment.apps/k8s-athenz-syncer created
Verify: Does it work?
Please refer to the Result section above to see the verification steps and outcome.
What I learned
Here's what I've learned:
- I discovered that when members change in a Trusted Domain (delegated role), the Modified Date and ETag of the Provider Domain do NOT change.
- I learned that
CustomResourceDefinition'sv1beta1API has been deprecated - I learned that you can enforce type in CRD
What's next?
I will dive into jag token and how Athenz integrates with it, and what Athenz lacks so far.
Dive Hours: 24.5 Hours
[!NOTE]
aegisthat utilizes syncer's CRD and kubernetes RBAC enforcer has been stopped as they do not sync super well yet.
-
1/1 Thu: 6.75 Hours -
1/2 Fri: 4.75 Hours -
1/3 Sat: 6.5 Hours -
1/11 Sun: 6.5 Hours
With the separate PRs of the following:
- https://github.com/mlajkim/aegis/pull/1
- https://github.com/mlajkim/dive-manifest/pull/1
- https://github.com/mlajkim/dive-manifest/pull/2
- https://github.com/mlajkim/dive-manifest/pull/3
- https://github.com/AthenZ/k8s-athenz-syncer/pull/45
- https://github.com/AthenZ/athenz/pull/3166
Closing
If you enjoyed this deep dive, please leave a like & subscribe for more!




Top comments (0)