The use of environment variables when the DEA launches application instance in Cloud Foundry

Source: Internet
Author: User

In Cloud Foundry v2, when an app user needs to launch an instance of the app. The user sends a request to the cloud controller via the CF CLI, and the cloud controller forwards the request to the DEA via Nats. The real start-up is Dea,dea's main job is to start a Warden container, and copy the droplet and other content into the container interior. Finally, the specified environment variables are configured to start the app's startup script under these environment variables.


This article will explain how the DEA in cloud Foundry configures environment variables for the launch of an application instance.


DEA receive application start request and its running flow


In this section, the code is used to illustrate the flow of the DEA to the application launch request.

  1. First, the DEA subscribes to the message of the subject, "Dea.#{bootstrap.uuid}.start", meaning "self-DEA Application initiation message":
          Subscribe ("Dea.#{bootstrap.uuid}.start") do |message|        Bootstrap.handle_dea_directed_start (message)      end
  2. After you receive the subscription topic, run Bootstrap.handle_dea_directed_start (message), meaning "to process the application's start request through the Bootstrap class instance":
        def handle_dea_directed_start (message)      Start_app (message.data)    end
  3. Able to feel the handling of the entrance. That is, the Start_app method in the above code:
        def start_app (data)      instance = instance_manager.create_instance (data)      return unless instance      Instance.start    End
  4. In the Start_app method. First, a instance object is created through the Instance_manager class instance. By running the class method of the instance instance start, you can see from beginning to finish. The original source of the passed reference is a message that is delivered through NATS messages. The message in 1:
        def start (&callback)      p = promise.new do ...        [          Promise_droplet,          promise_container        ].each (&:run). each (&:resolve)        [          promise_ Extract_droplet,          promise_exec_hook_script (' Before_start '),          promise_start        ].each (&:resolve)      ...        P.deliver      End
  5. The real implementation of the application launch is implemented in the Promise_start method:
        def Promise_start Promise.new do |p| env = Env.new (Startmessage.new (@raw_attributes), self) if staged_info command = Start_command | | staged_info[' start_command ' unless command P.fail (missingstartcommand.new) Next E nd start_script = dea::startupscriptgenerator.new (Command, Env.exported_use          R_environment_variables, env.exported_system_environment_variables). Generate Else Start_script = Env.exported_environment_variables + "./startup;\nexit" End response = Container.spawn (start _script, Container.resource_limits (Self.file_descriptor_limit, nproc_limit)) attr ibutes[' warden_job_id ' = response.job_id container.update_path_and_ip bootstrap.snapshot.save P.deli Ver End End

Can see in the 5th step. DEA involves the application of env environment variables and other information. Finally, the application start-up is realized by Container.spawn method.


Configuration of DEA environment variables


In step 5th of the above steps, you first created the environment variable ENV = env.new (Startmessage.new (@raw_attributes), self). The initialization method for the Env class is as follows:

    DEF initialize (message, instance_or_staging_task=nil)      @strategy_env = if message.is_a? Stagingmessage        stagingenv.new (message, instance_or_staging_task)      else        runningenv.new (message, Instance_or_staging_task)      End    End

Visible. An instance of the Runningenv class is actually created. The main parameters are the information sent by the cloud controller.


In the Promise_start method, after the env variable is created, the build of the Start_script variable is selected by inferring the Staged_info.


Now analyze the Staged_info code implementation:

    def staged_info      @staged_info | | = Begin        Dir.mktmpdir do |destination_dir|          Staging_file_name = ' staging_info.yml '          copied_file_name = ' #{destination_dir}/#{staging_file_name} '          Copy_ Out_request ("/home/vcap/#{staging_file_name}", Destination_dir)          yaml.load_file (copied_file_name) if File.exists? (copied_file_name)        End End End    

This is done primarily by specifying the path and then extracting the variable from the path. The following is an example of a ruby application where the contents of the Staging_info.yml file are:

---detected_buildpack:ruby/rackstart_command:bundle exec rackup config.ru-p $PORT

So, finally @staged_info the content as above. In the Instance.start method, command is the bundle EXEC rackup config.ru-p $PORT.

With the command variable, then build the Start_script variable:

          Start_script =            dea::startupscriptgenerator.new (              command,              env.exported_user_environment_variables,              env.exported_system_environment_variables            ). Generate

It can be seen that the DEA creates the Start_script through the Startupscriptgenerator class, with a number of three. The first one for the command that was just involved, the latter two need to be generated by the ENV variable.


Now look at the implementation of the Exported_user_environment_variables method:

    def exported_user_environment_variables      To_export (translate_env (message.env))    end

The method implements the information extracted from the message with the property as Env, as the user's environment variable.


The method of entering Env.exported_system_environment_variables is implemented:

    def exported_system_environment_variables      env = [        ["Vcap_application",  Yajl::encoder.encode (vcap_ application)],        ["Vcap_services",     Yajl::encoder.encode (vcap_services)],        ["Memory_limit", "#{ Message.mem_limit}m "]      env << [" Database_url ", Databaseurigenerator.new (message.services). DATABASE _uri] if Message.services.any?      To_export (env + strategy_env.exported_system_environment_variables)    end

When generating the environment variables of the system, we first create an env array variable, which has information vcap_application, vcap_services, memory_limit three kinds. Among the vcap_application information, such as the following:

    def vcap_application      @vcap_application | | =        begin          hash = strategy_env.vcap_application          hash["limits"] = message.limits          hash["Application_ Version "] = message.version          hash[" application_name "] = message.name          hash[" application_uris "] = Message.uris          # Translate keys for backwards compatibility          hash["version"] = hash["Application_version"]          hash["name"] = hash["Application_name"]          hash["URIs"] = hash["Application_uris"]          hash["users"] = hash["Application_ Users "]          hash        end    End

This part of the information includes the application of Name,uris,users,version and a series of content. It is important to note that the code hash = strategy_env.vcap_application, which is used to invoke the Vcap_application method in the Runningenv class, such as the following:

   def vcap_application      hash = {}      hash["instance_id"] = instance.attributes["instance_id"]      hash["Instance_ Index "] = Message.index      hash[" host "] = Hoststartupscriptgenerator      hash[" port "] = Instance.instance_container _port      started_at = time.at (instance.state_starting_timestamp)      hash["started_at"] = started_at      hash[" Started_at_timestamp "] = started_at.to_i      hash[" start "] = hash[" Started_at "]      hash[" state_timestamp "] = hash[ "Started_at_timestamp"]      hash    end

Visible in the above code, vcap_application information is recorded in a lot of information about the application instance, including INSTANCE_ID, Instance_index, host, Port, Started_at, Started_at_ Timestamp, start, state_timestamp and so on.



Vcap_services information such as the following:

    Whitelist_service_keys =%w[name Label Tags plan plan_option credentials syslog_drain_url].freeze    def vcap_services      @vcap_services | | =        begin          Services_hash = hash.new {|h, k| h[k] = []}          Message.services.each do |service|            Service_hash = {}            whitelist_service_keys.each do |key|              Service_hash[key] = Service[key] If Service[key]            end            services_hash[service["label"] "<< Service_hash          End          Services_hash        end    End

This part of the content is mainly from the message to find whether there is a value in the Whitelist_services_keys value as the key, if present, increase services_hash the variable.

Subsequently, the DEA executes code in env << ["Database_url", Databaseurigenerator.new (message.services). Database_uri] If Message.services.any, the role of this part of the code mainly to understand the meaning of databaseurigenerator, this part of the author is still not very clear.


And then later. DEA Run code to_export (env + strategy_env.exported_system_environment_variables), this part of the content is important, mainly to enter the Strategy_ View the Exported_system_environment_variables method in the class where the Env object is located:

    def exported_system_environment_variables      env = [        ["HOME", "$PWD/app"],        ["TMPDIR", "$PWD/tmp"],        [" Vcap_app_host ", HOST],        [" Vcap_app_port ", Instance.instance_container_port],      ]      env << [" PORT "," $ Vcap_app_port "]      env    End

Can see, here mainly includes the execution information environment variables, such as home folder, tmp temporary folder, the application instance executes the host address, the application instance executes the port number. The most important of these is the port number that the application instance executes. There's one more blog in mine. In the Cloud Foundry, the DEA and Warden communication has been applied in port monitoring. There is a startup script that involves how to open a port through Warden server, which is finally used by the DEA and passed to the application instance in the form of an environment variable. Both Vcap_app_port and port are Warden container open the port number.


After analyzing the three parameters of startupscriptgenerator, you need to enter the Generate method of the Startupscriptgenerator class:

    def generate      script = []      script << "umask 077"      script << @system_envs      script << EXPORT _buildpack_env_variables_script      Script << @user_envs      script << "ENV > Logs/env.log"      Script << start_script% @start_command      script.join ("\ n")    end

The code above is the process of creating a startup script. Among them, @system_envs is the env.exported_system_environment_variables of the previous analysis, @user_envs is Env.exported_user_environment_ Variables

There are also two scripts that are Export_buildpack_env_variables_script and start_script. The code for the Export_buildpack_env_variables_script script, such as the following, is intended to run all SH scripts under a path:

    Export_buildpack_env_variables_script = Strip_heredoc (<<-bash). Freeze      unset Gem_path      If [-D app/. PROFILE.D]; Then for        i in app/.profile.d/*.sh, do          if [-R $i];            $i          fi done        unset i      fi    BASH

The Start_script code, for example, is:

    Start_script = Strip_heredoc (<<-bash). Freeze      droplet_base_dir= $PWD      CD app      (%s) > > (Tee $ Droplet_base_dir/logs/stdout.log) 2> > (Tee $DROPLET _base_dir/logs/stderr.log >&2) &      started=$!      echo "$STARTED" >> $DROPLET _base_dir/run.pid      wait $STARTED    BASH

Above that is created Start_script, back to instance.rb in the Promise_start method, that is, run
Response = Container.spawn (Start_script,                                   container.resource_limits (Self.file_descriptor_limit, NPROC_LIMIT))

The start of the application instance is complete. Details can be entered into the container class in the Spawn method implementation.


About

Liang Daocloud software Project Master. In the past two years, we have studied the knowledge and technology of PAAs in the field of cloud computing. Believing in the technology of lightweight virtualization containers will have a deep impact on the PAAs landscape and even determine the future of PAAs technology.



Reprint please indicate the source.

Many of the other things in my own understanding, there must be deficiencies and errors in some places. I hope this article can be of some help to the people who contact the DEA environment variables, if you are interested in this area, and have better ideas and suggestions, please contact me.

my e-mail: [Email protected]Sina Micro-blog:@ Lotus seeds and clear



The use of environment variables when the DEA launches application instance in Cloud Foundry

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.