Git Fileserver Backend Walkthrough

注解

This walkthrough assumes basic knowledge of Salt. To get up to speed, check out the Salt Walkthrough.

The gitfs backend allows Salt to serve files from git repositories. It can be enabled by adding git to the fileserver_backend list, and configuring one or more repositories in gitfs_remotes.

Branches and tags become Salt fileserver environments.

安装依赖

Beginning with version 2014.7.0, both pygit2 and Dulwich are supported as alternatives to GitPython. The desired provider can be configured using the gitfs_provider parameter in the master config file.

If gitfs_provider is not configured, then Salt will prefer pygit2 if a suitable version is available, followed by GitPython and Dulwich.

注解

It is recommended to always run the most recent version of any the below dependencies. Certain features of gitfs may not be available without the most recent version of the chosen library.

pygit2

The minimum supported version of pygit2 is 0.20.3. Availability for this version of pygit2 is still limited, though the SaltStack team is working to get compatible versions available for as many platforms as possible.

For the Fedora/EPEL versions which have a new enough version packaged, the following command would be used to install pygit2:

# yum install python-pygit2

Provided a valid version is packaged for Debian/Ubuntu (which is not currently the case), the package name would be the same, and the following command would be used to install it:

# apt-get install python-pygit2

If pygit2 is not packaged for the platform on which the Master is running, the pygit2 website has installation instructions here. Keep in mind however that following these instructions will install libgit2 and pygit2 without system packages. Additionally, keep in mind that SSH authentication in pygit2 requires libssh2 (not libssh) development libraries to be present before libgit2 is built. On some distros (debian based) pkg-config is also required to link libgit2 with libssh2.

警告

pygit2 is actively developed and frequently makes non-backwards-compatible API changes, even in minor releases. It is not uncommon for pygit2 upgrades to result in errors in Salt. Please take care when upgrading pygit2, and pay close attention to the changelog, keeping an eye out for API changes. Errors can be reported on the SaltStack issue tracker.

GitPython

GitPython 0.3.0 or newer is required to use GitPython for gitfs. For RHEL-based Linux distros, a compatible version is available in EPEL, and can be easily installed on the master using yum:

# yum install GitPython

Ubuntu 14.04 LTS和Debian Wheezy (7.x) 同样有兼容版本的安装包:

# apt-get install python-git

如果你的master运行在老版本系统上(类似于Ubuntu12.04LTS或Debian Squeeze),那么你必须使用pip或easy_install(建议使用pip)来安装GitPython。0.3.2.RC1是当前在PyPi中的稳定版本,所以使用root来运行``pip install GitPython``(或``easy_install GitPython``)应该是件简单的事情。

警告

记住,如果GitPython在master上已经使用pip安装过(即使它随后被卸载了),并且在安装之后没有清理缓存,那么它可能还存在于生成缓存(通常在``/tmp/pip-build-root/GitPython``) 。生成缓存中的包会覆盖任何要求说明,所以如果你使用``pip install GitPython==0.3.2.RC1``尝试将版本升级到0.3.2.RC1,那么它将被忽略并且只会从缓存目录来安装版本。因此,需要从生成缓存中删除 GitPython 目录,以确保指定的版本的安装。

Dulwich

Dulwich 0.9.4 or newer is required to use Dulwich as backend for gitfs.

Dulwich is available in EPEL, and can be easily installed on the master using yum:

# yum install python-dulwich

For APT-based distros such as Ubuntu and Debian:

# apt-get install python-dulwich

重要

If switching to Dulwich from GitPython/pygit2, or switching from GitPython/pygit2 to Dulwich, it is necessary to clear the gitfs cache to avoid unpredictable behavior. This is probably a good idea whenever switching to a new gitfs_provider, but it is less important when switching between GitPython and pygit2.

Beginning in version 2015.5.0, the gitfs cache can be easily cleared using the fileserver.clear_cache runner.

salt-run fileserver.clear_cache backend=git

If the Master is running an earlier version, then the cache can be cleared by removing the gitfs and file_lists/gitfs directories (both paths relative to the master cache directory, usually /var/cache/salt/master).

rm -rf /var/cache/salt/master{,/file_lists}/gitfs

基本配置

使用gitfs backend,只需要在master上修改两个配置:

  1. Include git in the fileserver_backend list in the master config file:

    fileserver_backend:
      - git
    
  2. Specify one or more git://, https://, file://, or ssh:// URLs in gitfs_remotes to configure which repositories to cache and search for requested files:

    gitfs_remotes:
      - https://github.com/saltstack-formulas/salt-formula.git
    

    SSH remotes can also be configured using scp-like syntax:

    gitfs_remotes:
      - git@github.com:user/repo.git
      - ssh://user@domain.tld/path/to/repo.git
    

    Information on how to authenticate to SSH remotes can be found here.

    注解

    Dulwich does not recognize ssh:// URLs, git+ssh:// must be used instead. Salt version 2015.5.0 and later will automatically add the git+ to the beginning of these URLs before fetching, but earlier Salt versions will fail to fetch unless the URL is specified using git+ssh://.

  3. 重启控制器来加载新的配置文件

注解

In a master/minion setup, files from a gitfs remote are cached once by the master, so minions do not need direct access to the git repository.

多远程仓库

gitfs_remotes 选项接受一个有序的git remotes列表,该顺序列表用于缓存和搜索所请求的文件。

一个简单的场景说明了这种级联的查找行为:

如果 gitfs_remotes 选项指定了三个remotes:

gitfs_remotes:
  - git://github.com/example/first.git
  - https://github.com/example/second.git
  - file:///root/third

每个版本库包含一些文件:

first.git:
    top.sls
    edit/vim.sls
    edit/vimrc
    nginx/init.sls

second.git:
    edit/dev_vimrc
    haproxy/init.sls

third:
    haproxy/haproxy.conf
    edit/dev_vimrc

Salt will attempt to lookup the requested file from each gitfs remote repository in the order in which they are defined in the configuration. The git://github.com/example/first.git remote will be searched first. If the requested file is found, then it is served and no further searching is executed. For example:

  • A request for the file salt://haproxy/init.sls will be served from the https://github.com/example/second.git git repo.
  • A request for the file salt://haproxy/haproxy.conf will be served from the file:///root/third repo.

注解

本例只是用于介绍如何使用gitfs后端,并不建议在实际环境中这样布局文件及git仓库.

file:// 前缀指定了本地的文件夹作为git仓库. 然而,salt依然会使用给定的 file:// URL作为一个远端仓库, 而不是直接拷贝git仓库到salt的缓存中. 这意味着需要的refs需要在指定的仓库中存在.

警告

2014.1.0之前的salt版本不能改变remotes的顺序或修改已有remotes的URI。在这些版本中,当修改remotes,重启salt-master服务之前,最好先删除gitfs缓存目录 (/var/cache/salt/master/gitfs)

Per-remote Configuration Parameters

2014.7.0 新版功能.

The following master config parameters are global (that is, they apply to all configured gitfs remotes):

These parameters can now be overridden on a per-remote basis. This allows for a tremendous amount of customization. Here's some example usage:

gitfs_provider: pygit2
gitfs_base: develop

gitfs_remotes:
  - https://foo.com/foo.git
  - https://foo.com/bar.git:
    - root: salt
    - mountpoint: salt://foo/bar/baz
    - base: salt-base
  - http://foo.com/baz.git:
    - root: salt/states
    - user: joe
    - password: mysupersecretpassword
    - insecure_auth: True

重要

There are two important distinctions which should be noted for per-remote configuration:

  1. The URL of a remote which has per-remote configuration must be suffixed with a colon.
  2. Per-remote configuration parameters are named like the global versions, with the gitfs_ removed from the beginning.

In the example configuration above, the following is true:

  1. The first and third gitfs remotes will use the develop branch/tag as the base environment, while the second one will use the salt-base branch/tag as the base environment.
  2. The first remote will serve all files in the repository. The second remote will only serve files from the salt directory (and its subdirectories), while the third remote will only serve files from the salt/states directory (and its subdirectories).
  3. The files from the second remote will be located under salt://foo/bar/baz, while the files from the first and third remotes will be located under the root of the Salt fileserver namespace (salt://).
  4. The third remote overrides the default behavior of not authenticating to insecure (non-HTTPS) remotes.

子目录

The gitfs_root parameter allows files to be served from a subdirectory within the repository. This allows for only part of a repository to be exposed to the Salt fileserver.

假设下面的布局:

.gitignore
README.txt
foo/
foo/bar/
foo/bar/one.txt
foo/bar/two.txt
foo/bar/three.txt
foo/baz/
foo/baz/top.sls
foo/baz/edit/vim.sls
foo/baz/edit/vimrc
foo/baz/nginx/init.sls

The below configuration would serve only the files under foo/baz, ignoring the other files in the repository:

gitfs_remotes:
  - git://mydomain.com/stuff.git

gitfs_root: foo/baz

The root can also be configured on a per-remote basis.

Mountpoints

2014.7.0 新版功能.

The gitfs_mountpoint parameter will prepend the specified path to the files served from gitfs. This allows an existing repository to be used, rather than needing to reorganize a repository or design it around the layout of the Salt fileserver.

Before the addition of this feature, if a file being served up via gitfs was deeply nested within the root directory (for example, salt://webapps/foo/files/foo.conf, it would be necessary to ensure that the file was properly located in the remote repository, and that all of the the parent directories were present (for example, the directories webapps/foo/files/ would need to exist at the root of the repository).

The below example would allow for a file foo.conf at the root of the repository to be served up from the Salt fileserver path salt://webapps/foo/files/foo.conf.

gitfs_remotes:
  - https://mydomain.com/stuff.git

gitfs_mountpoint: salt://webapps/foo/files

Mountpoints can also be configured on a per-remote basis.

Using gitfs Alongside Other Backends

有时它可能会有意识的使用多个后端 ;例如,如果``sls`` 文件被存储在git上,而大多数文件被直接存储在master上。

级联的查找逻辑用于多remotes,也同样应用于多个backends。如果``fileserver_backend`` 选项包含多个backends:

fileserver_backend:
  - roots
  - git

那么 roots backend( 默认文件的backend在``/srv/salt``中)将会首先被请求文件搜索;然后,如果在master上没有找到,将会搜索每个配置的git remote。

Branches, Environments, and Top Files

When using the gitfs backend, branches, and tags will be mapped to environments using the branch/tag name as an identifier.

这里有一个例外: master branch 隐含映射到 base environment。

所以,一个典型的 base, qa, dev 设置中,以下的branches可以使用:

master
qa
dev

top.sls files from different branches will be merged into one at runtime. Since this can lead to overly complex configurations, the recommended setup is to have a separate repository, containing only the top.sls file with just one single master branch.

要映射一个不同于``master``的 branch,使用 gitfs_base 参数。

gitfs_base: salt-base

The base can also be configured on a per-remote basis.

Environment Whitelist/Blacklist

2014.7.0 新版功能.

The gitfs_env_whitelist and gitfs_env_blacklist parameters allow for greater control over which branches/tags are exposed as fileserver environments. Exact matches, globs, and regular expressions are supported, and are evaluated in that order. If using a regular expression, ^ and $ must be omitted, and the expression must match the entire branch/tag.

gitfs_env_whitelist:
  - base
  - v1.*
  - 'mybranch\d+'

注解

v1.*, in this example, will match as both a glob and a regular expression (though it will have been matched as a glob, since globs are evaluated before regular expressions).

The behavior of the blacklist/whitelist will differ depending on which combination of the two options is used:

  • If only gitfs_env_whitelist is used, then only branches/tags which match the whitelist will be available as environments
  • If only gitfs_env_blacklist is used, then the branches/tags which match the blacklist will not be available as environments
  • If both are used, then the branches/tags which match the whitelist, but do not match the blacklist, will be available as environments.

Authentication

pygit2

2014.7.0 新版功能.

Both HTTPS and SSH authentication are supported as of version 0.20.3, which is the earliest version of pygit2 supported by Salt for gitfs.

注解

The examples below make use of per-remote configuration parameters, a feature new to Salt 2014.7.0. More information on these can be found here.

HTTPS

For HTTPS repositories which require authentication, the username and password can be provided like so:

gitfs_remotes:
  - https://domain.tld/myrepo.git:
    - user: git
    - password: mypassword

If the repository is served over HTTP instead of HTTPS, then Salt will by default refuse to authenticate to it. This behavior can be overridden by adding an insecure_auth parameter:

gitfs_remotes:
  - http://domain.tld/insecure_repo.git:
    - user: git
    - password: mypassword
    - insecure_auth: True

SSH

SSH repositories can be configured using the ssh:// protocol designation, or using scp-like syntax. So, the following two configurations are equivalent:

  • ssh://git@github.com/user/repo.git
  • git@github.com:user/repo.git

Both gitfs_pubkey and gitfs_privkey (or their per-remote counterparts) must be configured in order to authenticate to SSH-based repos. If the private key is protected with a passphrase, it can be configured using gitfs_passphrase (or simply passphrase if being configured per-remote). For example:

gitfs_remotes:
  - git@github.com:user/repo.git:
    - pubkey: /root/.ssh/id_rsa.pub
    - privkey: /root/.ssh/id_rsa
    - passphrase: myawesomepassphrase

Finally, the SSH host key must be added to the known_hosts file.

GitPython

With GitPython, only passphrase-less SSH public key authentication is supported. The auth parameters (pubkey, privkey, etc.) shown in the pygit2 authentication examples above do not work with GitPython.

gitfs_remotes:
  - ssh://git@github.com/example/salt-states.git

Since GitPython wraps the git CLI, the private key must be located in ~/.ssh/id_rsa for the user under which the Master is running, and should have permissions of 0600. Also, in the absence of a user in the repo URL, GitPython will (just as SSH does) attempt to login as the current user (in other words, the user under which the Master is running, usually root).

If a key needs to be used, then ~/.ssh/config can be configured to use the desired key. Information on how to do this can be found by viewing the manpage for ssh_config. Here's an example entry which can be added to the ~/.ssh/config to use an alternate key for gitfs:

Host github.com
    IdentityFile /root/.ssh/id_rsa_gitfs

The Host parameter should be a hostname (or hostname glob) that matches the domain name of the git repository.

It is also necessary to add the SSH host key to the known_hosts file. The exception to this would be if strict host key checking is disabled, which can be done by adding StrictHostKeyChecking no to the entry in ~/.ssh/config

Host github.com
    IdentityFile /root/.ssh/id_rsa_gitfs
    StrictHostKeyChecking no

However, this is generally regarded as insecure, and is not recommended.

Adding the SSH Host Key to the known_hosts File

To use SSH authentication, it is necessary to have the remote repository's SSH host key in the ~/.ssh/known_hosts file. If the master is also a minion, this can be done using the ssh.set_known_host function:

# salt mymaster ssh.set_known_host user=root hostname=github.com
mymaster:
    ----------
    new:
        ----------
        enc:
            ssh-rsa
        fingerprint:
            16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
        hostname:
            |1|OiefWWqOD4kwO3BhoIGa0loR5AA=|BIXVtmcTbPER+68HvXmceodDcfI=
        key:
            AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
    old:
        None
    status:
        updated

If not, then the easiest way to add the key is to su to the user (usually root) under which the salt-master runs and attempt to login to the server via SSH:

$ su
Password:
# ssh github.com
The authenticity of host 'github.com (192.30.252.128)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.252.128' (RSA) to the list of known hosts.
Permission denied (publickey).

It doesn't matter if the login was successful, as answering yes will write the fingerprint to the known_hosts file.

Verifying the Fingerprint

To verify that the correct fingerprint was added, it is a good idea to look it up. One way to do this is to use nmap:

$ nmap github.com --script ssh-hostkey

Starting Nmap 5.51 ( http://nmap.org ) at 2014-08-18 17:47 CDT
Nmap scan report for github.com (192.30.252.129)
Host is up (0.17s latency).
Not shown: 996 filtered ports
PORT     STATE SERVICE
22/tcp   open  ssh
| ssh-hostkey: 1024 ad:1c:08:a4:40:e3:6f:9c:f5:66:26:5d:4b:33:5d:8c (DSA)
|_2048 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 (RSA)
80/tcp   open  http
443/tcp  open  https
9418/tcp open  git

Nmap done: 1 IP address (1 host up) scanned in 28.78 seconds

Another way is to check one's own known_hosts file, using this one-liner:

$ ssh-keygen -l -f /dev/stdin <<<`ssh-keyscan -t rsa github.com 2>/dev/null` | awk '{print $2}'
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48

Refreshing gitfs Upon Push

默认情况下,Salt每60秒更新remote文件服务器后端。但是,如果希望快速的刷新后端, Reactor System 可以用信号通知master来更新每个推送的文件服务器,这些服务器由git服务器来提供,它也可以是Salt minion。这一过程有三个步骤:

  1. On the master, create a file /srv/reactor/update_fileserver.sls, with the following contents:

    update_fileserver:
      runner.fileserver.update
    
  2. 添加下列反应器配置到master 配置文件:

    reactor:
      - 'salt/fileserver/gitfs/update':
        - /srv/reactor/update_fileserver.sls
    
  3. 在git服务器上,添加一个 `post-receive hook`_包含以下内容:

    #!/usr/bin/env sh
    
    salt-call event.fire_master update salt/fileserver/gitfs/update
    

The update argument right after event.fire_master in this example can really be anything, as it represents the data being passed in the event, and the passed data is ignored by this reactor.

同样地,tag名称 salt/fileserver/gitfs/update 可以被任意替代,只要用法是一致的就可以。

使用Git作为一个外部Pillar来源

The git external pillar (a.k.a. git_pillar) has been rewritten for the 2015.8.0 release. This rewrite brings with it pygit2 support (allowing for access to authenticated repositories), as well as more granular support for per-remote configuration.

To make use of the new features, changes to the git ext_pillar configuration must be made. The new configuration schema is detailed here.

For Salt releases before 2015.8.0, click here for documentation.

为什么自定义的模块/states等等不会同步到Minions上?

在0.16.3及之前的版本, 当使用 git文件服务后端 时,某些版本的GitPython可能会在fetch时产生错误, 导致Salt抓取失败。虽然对于fetch过程来说这并不致命,但是中断文件服务发生在自定义类型同步完成之前发生,这样会中断同步过程本身。请尝试关闭掉master配置中的git文件服务后端, 重启master并尝试再次同步.

这个问题在Salt 0.16.4及最新的版本已经得到解决.