An example of using dynamic client of

In this article, I describe how to write a Kubernetes client in Go using the dynamic client in package. During the course, you can learn the following things:

  • The difference between typed clients and the dynamic client.
  • Reading YAML manifests into unstructured.Unstructured.
  • Discovering the REST API endpoint for a Group-Version-Kind.
  • Creating and updating resources using Server Side Apply.

You should have a basic knowledge of Kubernetes and Go programming. The examples in this article depend on

  • Background: Server Side Apply
  • Kubernetes API Basics
    • Mapping between GVK and GVR
  • Go client libraries
    • Typed clients
    • Dynamic client
  • Using the dynamic client to implement SSA

Background: Server Side Apply

Recently, I wrote a program that applies Kubernetes resources using Server Side Apply. Server Side Apply, or SSA, is a new way to create or update resources in Kubernetes API server added as a beta feature to Kubernetes 1.16.

One of the advantage of SSA is that it introduces better patching strategy than Strategic Merge Patch. For example, if a Service has two ports sharing the same port number but with different protocol, Strategic Merge Patch could not identify which port should be updated because it uses port as the key.

apiVersion: v1
kind: Service
  name: mydns
    app: mydns
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
Read more

Writing and testing Kubernetes webhooks using Kubebuilder v2

Recently, I am leading a project to re-design our on-premise data centers using Kubernetes. Inevitably there are opportunities to develop Kubernetes native applications.

The architecture of Kubernetes is like "hub-and-spoke"; the center of the system is kube-apiserver and all other programs communicate with it.


To customize Kubernetes, kube-apiserver provides the following functions:

This article describes how to implement and test webhooks using Kubebuilder v2. Be warned that the contents are lengthy and meant for professionals.

Read more

Making well-behaved programs in Go with cybozu-go/cmd

We at are using Go for variety of tasks.

In early days when we started using Go, there were only few in-house rules to create commands. As a result, we faced several difficulties:

  • Some servers did not record access logs.
  • Some programs did not record command execution logs.
  • No common spec to handle SIGINT or SIGTERM.
  • Some programs did not reopen log files, making log rotation difficult.
  • Inconsistent log formats.
Read more

Introducing go-apt-cacher and go-apt-mirror

go-apt-cacher is a caching reverse-proxy designed specially for Debian/Ubuntu repositories. As it is written in Go, go-apt-cacher tolerates thousands of concurrent client connections and is very fast.

go-apt-mirror is a mirroring tool for Debian/Ubuntu repositories similar to apt-mirror. The biggest advantage of using go-apt-mirror is that it will never create incomplete/inconsistent mirrors.

This article describes our backgrounds and motivation as well as the design of these tools. They are available at

Read more

Transparent SOCKS proxy in Go to replace NAT

I am working behind a cloud service as an infrastructure engineer. My recent work was the replacement of NAT inside our data center with a transparent SOCKS proxy.

In this post, I will describe our motivation for the replacement and how we can do it using Go effectively.


  • NAT has deficiencies in routing, connectivity, and access control.
  • We made a transparent SOCKS proxy transocks to replace NAT.
  • Using iptables is far better than LD_PRELOAD for transparent proxy.
  • We made our own SOCKS5 server usocksd too.
Read more

Split a string in C++11

The example below works just like PHP's explode.

std::vector<std::string> tokenize(const std::string& s, char c) {
    auto end = s.cend();
    auto start = end;

    std::vector<std::string> v;
    for( auto it = s.cbegin(); it != end; ++it ) {
        if( *it != c ) {
            if( start == end )
                start = it;
        if( start != end ) {
            v.emplace_back(start, it);
            start = end;
    if( start != end )
        v.emplace_back(start, end);
    return v;


auto v = tokenize(" abc  def ", ' ');

v == std::vector<std::string>{"abc", "def"}; // true

Simple and efficient.