14

Note a similar question has been asked:
How to pass flags when starting 'service'?
But I read a while back that Linux switched from init.d to systemd, and since that Q&A are 6 years old I thought it might refer to init.d

My question is:
How do you pass flags/arguments when starting a systemd service? Let's say I do systemctl restart Kubelet, that means I have the Kubelet Service running, well how could I see and modify what Flags/Arguements are passed to that service? (Such as --anonymous-auth=false)

Also here's some Context:
I'm close to scheduling my CNCF Kubernetes Certification Exam, the exam is performance-based and covers some nitty gritty stuff that's usually abstracted away from a Cluster Admin.

Something I learned is that there are 7 core Binary's that makeup Kubernetes: [docker, etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kube-proxy, and kubelet]

Some of these Kubernetes control plane binaries are "self hosted"/run as pods on Kubernetes, and you pass args/flags like --service-cluster-ip-range=10.0.0.0/16

The following URL has an example of some core binaries being run as Docker containers on Kubernetes, and the flags being passed in as Arguments in the YAML specification. https://kubernetes.io/docs/setup/scratch/#scheduler-pod-template

Other Core Kubernetes Binaries like Kubelet and Docker aren't well suited for self hosting and are instead run as Linux System Daemons, and they run using systemd and are managed with systemctl and journalctl. Anyways I've had to login to a node and do systemctl restart docker.service and systemctl restart kubelet.service before, but I don't actually know how to see or modify what flags/Arguments are passed to them.

neoakris
  • 263

4 Answers4

17

From here this can be done like so:

  1. Create an arguments file say /etc/.argconf

    ARG1=-o
    ARG2=--verbose
    
  2. And your .service file:

    EnvironmentFile=/etc/.argconf
    ExecStart=/usr/bin/prog $ARG1 $ARG2
    

Another method from that same post is as seen below:

[Unit]
Description=Test passing multiple arguments

[Service]
Environment="SCRIPT_ARGS=%I"
ExecStart=/tmp/test.py $SCRIPT_ARGS

And the name of the file has to be myservice@.service take note of the @ as this is required when passing arguments in this fashion to a service. You then run that service like so:

sudo systemctl start myservice@"arg1 arg2 arg3".service
Xunnamius
  • 113
  • 5
George Udosen
  • 36,677
  • 1
    Thank you for pointing me in the right direction and answering my quest, I guess I should have looked on other stack overflows 1st. – neoakris Sep 23 '18 at 22:10
  • For running the service with arguments passed via %I consider using the tool systemd-escape especially when special characters such as "-" shall be part of the arg's. – Bl00dh0und Jun 07 '22 at 16:31
  • Is it possible to take one of the ARGs and use it by itself? E.g. A User=$ARG1 line, while using the service@"arg1 arg2" notation? – Sam Sirry Jul 10 '22 at 21:58
  • How would you start such a service from timer unit? – deanresin Nov 20 '23 at 02:17
4

TL;DR

When we run systemctl start <name>.service systemd really executes /lib/systemd/system/<name>.service

This may be helpful for other newbies like me.

Let's run a service and check the status (in fail or success):

systemctl start <name>.service 
systemctl status <name>.service

You will find this line on the output for the status:

/lib/systemd/system/<name>.service

That's the file systemd executes. If you follow that path and open using Vim, it's the structure shown by the accepted answer.


As to where to put the files, I can't give an opinion, but at least we know what file systemd is reading.

2

Just like how every implementation/flavor/distribution of Linux is a little different.
I learned that every implementation of Kuberntes is a little different.
And that there's different ways to implement systemd.

With all that variability I believe the best way to do this seems to be:
To use the find command to find where *.service is located

WorkerNodeBash# find / -name "*.service" | grep -i "kube"
WorkerNodeBash# nano /etc/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \
  --config=/var/lib/kubelet/kubelet-config.yaml \
  --container-runtime=remote \
  --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \
  --image-pull-progress-deadline=2m \
  --kubeconfig=/var/lib/kubelet/kubeconfig \
  --network-plugin=cni \
  --register-node=true \
  --pod-manifest-path=/etc/kubernetes/manifests \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

(The above comes from Kubernetes the hard way implementation, I've also done kubeadm and looked in this same file and saw no args, but thanks to learning how to use the find command I was able to search:
WorkerNodeBash# find / -type f -name "*.yaml" | grep "kube"
And I found a config file that mentioned KUBELET_EXTRA_ARGS=, and pass them in there.

neoakris
  • 263
2

While systemd does execute the file found in:

/lib/systemd/system/<name>.service

if you look in /etc/systemd/system you find a file <name>.service that is a link back to the file in /lib/systemd/system.

This is so you can remove the file from /etc/systemd/system but still have the file in /lib/systemd/system to allow you add it back if or when necessary.

ThunderBird
  • 1,955