Score:0

How can I configure an etcd cluster to work with salt stack master?

cn flag

The official documentation ( https://docs.saltproject.io/en/latest/ref/cache/all/salt.cache.etcd_cache.html#module-salt.cache.etcd_cache ) shows this example config:

etcd.host: 127.0.0.1
etcd.port: 2379
etcd.protocol: http
etcd.allow_reconnect: True
etcd.allow_redirect: False
etcd.srv_domain: None
etcd.read_timeout: 60
etcd.username: None
etcd.password: None
etcd.cert: None
etcd.ca_cert: None

In my particluar case, I have an etcd cluster with PKI (TLS cert based) authentication. The salt module documentation does not say any specific about that use case. It only says this:

Related docs could be found in the python-etcd documentation.

The "related documentation" is in fact very vague here https://python-etcd.readthedocs.io/en/latest/#create-a-client-object - it is not a real documentation, only a list of trivial examples:

import etcd

client = etcd.Client() # this will create a client against etcd server running on localhost on port 4001
client = etcd.Client(port=4002)
client = etcd.Client(host='127.0.0.1', port=4003)
client = etcd.Client(host='127.0.0.1', port=4003, allow_redirect=False) # wont let you run sensitive commands on non-leader machines, default is true
client = etcd.Client(
             host='127.0.0.1',
             port=4003,
             allow_reconnect=True,
             protocol='https',)

Of course none of this will work with a proper etcd cluster. However, the source code reveals that it is possible to give a list of hosts:

https://github.com/jplana/python-etcd/blob/master/src/etcd/client.py#L74

        Initialize the client.
        Args:
            host (mixed):
                           If a string, IP to connect to.
                           If a tuple ((host, port), (host, port), ...)

But I don't have any idea how to put a tuple of tuples into the salt master config file. This is what I have tried:

cache: etcd
etcd.host: [('salt1.lacinet', 2739), ('salt2.lacinet', 2739)]
etcd.protocol: https
etcd.allow_reconnect: True
etcd.allow_redirect: False
etcd.srv_domain: None
etcd.read_timeout: 60
etcd.username: root
etcd.password: None
etcd.cert: ('/etc/salt/etcd/root.key.pem', '/etc/salt/etcd/root.cert.pem')
etcd.ca_cert: '/etc/salt/etcd/ca.cert.pem'

But it results in an error:

[ERROR   ] Could not discover the etcd hosts from None: None of DNS query names exist: _etcd._tcp.None., _etcd._tcp.None.lacinet.
[ERROR   ] Failed to get list of machines from https://['salt1.lacinet', 'salt2.lacinet']:2379/v2: LocationParseError("Failed to parse: https://['salt1.lacinet', 'salt2.lacinet']:2379/v2/machines")
[ERROR   ] Error in function _pillar:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/etcd/client.py", line 296, in machines
    response = self.http.request(
  File "/usr/lib/python3/dist-packages/urllib3/request.py", line 75, in request
    return self.request_encode_url(
  File "/usr/lib/python3/dist-packages/urllib3/request.py", line 97, in request_encode_url
    return self.urlopen(method, url, **extra_kw)
  File "/usr/lib/python3/dist-packages/urllib3/poolmanager.py", line 318, in urlopen
    u = parse_url(url)
  File "/usr/lib/python3/dist-packages/urllib3/util/url.py", line 392, in parse_url
    return six.raise_from(LocationParseError(source_url), None)
  File "<string>", line 3, in raise_from
urllib3.exceptions.LocationParseError: Failed to parse: https://["('salt1.lacinet'", '2739)', "('salt1.lacinet'", '2739)']:2379/v2/machines

The error itself is very suspicious:

Failed to parse: https://["('salt1.lacinet'", '2739)', "('salt1.lacinet'", '2739)']:2379/v2/machines

I suspect that the host list is not recognized as a list or tuple, but as a string.

Given this error, it might even be possible that salt-master minion cache does not support multiple etcd hosts? But that would be very "interesting", since the main reason of installing etcd is to provide a HA key-value storage for multiple salt masters. What is the point if it can only use a single etcd server?

I'll likely have problems with the TLS cert based authentication as well, because it also uses a tuple (or it should, as given in https://github.com/jplana/python-etcd/blob/master/src/etcd/client.py#L90 ):


            cert (mixed):   If a string, the whole ssl client certificate;
                            if a tuple, the cert and key file names.
            ca_cert (str): The ca certificate. If pressent it will enable
                           validation.

It is not clear how to specify a tuple of filenames in the config. Also not clear if the ca_cert configuration is the path of a cert file, or it is the PEM cert string itself. None of this is documented anywhere (or just I could not find it).

Can anybody please tell me howto use a proper TLS-auth etcd cluster with salt-master as the minion cache? Is it possible at all?

cn flag
zero experience with this, but for several hosts it should be (( host, port ) ( host, port)) instead of [( host, port) (host, port)] (https://github.com/jplana/python-etcd/blob/b227f496c038b2b856c4d76c9525b3547e5c8dc4/src/etcd/client.py#L76)
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.